磁盘是块存储设备,读写连续的一整块磁盘数据其实还是很快的,平时我们感觉磁盘比内存慢是因为没有顺序地读磁盘,而是在随机读,大部分时间都浪费在寻道和旋转上面。
做个试验,对比一下顺序读磁盘和读写内存的速度,看看到底差多少。
试验方法:创建一个长度为10M的字节数组,执行3种操作--顺序地访问该数组里的元素,随机地访问该数组里的元素,把该数组里的元素顺序地写入磁盘。
试验结果:
结论:
1. 顺序读写内存比随机读写内存快几十倍
2.顺序读写磁盘比随机读写内存快几倍
CPU读写磁盘的最小单位是块,一块通常是4K,连续整块整块的读写会非常快。搜索引擎要存储海量的文档,它充分利用了磁盘的这一特性,提高文档读取的速度。对搜索引擎感兴趣的同学可以扫码进入我的课程--《Go语言实现工业级搜索引擎》。
最后附上测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | package serialize import ( "fmt" io "io" "math/rand" "os" "testing" "time" ) const SIZE = int(1e7) //不能再大了,否则会报错runtime: goroutine stack exceeds 1000000000-byte limit var ( arr [SIZE]byte indexes [SIZE]int ) func init() { for i := 0; i < SIZE; i++ { indexes[i] = i } rand.Seed(time.Now().UnixNano()) rand.Shuffle(SIZE, func (i, j int) { indexes[i], indexes[j] = indexes[j], indexes[i] }) } //顺序读内存 func TestReadRAMOrderly(t *testing.T) { begin := time.Now() for _, ele := range arr { _ = ele } fmt.Printf( "read RAM unorderly %d ms\n" , time.Since(begin).Milliseconds()) } //go test -v go_search_engine/forward_index/serialize -run=TestReadRAMOrderly //顺序写内存 func TestWriteRAMOrderly(t *testing.T) { begin := time.Now() for i := 0; i < SIZE; i++ { arr[i] = 1 } fmt.Printf( "write RAM unorderly %d ms\n" , time.Since(begin).Milliseconds()) } //go test -v go_search_engine/forward_index/serialize -run=TestWriteRAMOrderly //随机读内存 func TestReadRAMUnorderly(t *testing.T) { begin := time.Now() for _, i := range indexes { _ = arr[i] } fmt.Printf( "read RAM unorderly %d ms\n" , time.Since(begin).Milliseconds()) } //go test -v go_search_engine/forward_index/serialize -run=TestReadRAMUnorderly //随机写内存 func TestWriteRAMUnorderly(t *testing.T) { begin := time.Now() for _, i := range indexes { arr[i] = 1 } fmt.Printf( "write RAM unorderly %d ms\n" , time.Since(begin).Milliseconds()) } //go test -v go_search_engine/forward_index/serialize -run=TestWriteRAMUnorderly //顺序写磁盘 func TestWriteDiskOrderly(t *testing.T) { fout, err := os.OpenFile( "arr.txt" , os.O_RDWR|os.O_CREATE|os.O_TRUNC, os.ModePerm) if err != nil { panic(err) } begin := time.Now() fout.Write(arr[:]) //通过切片[:]把数组转slice fout.Close() fmt.Printf( "write disk orderly %d ms\n" , time.Since(begin).Milliseconds()) } //go test -v go_search_engine/forward_index/serialize -run=TestWriteDiskOrderly //顺序读磁盘 func TestReadDiskOrderly(t *testing.T) { fin, err := os.OpenFile( "arr.txt" , os.O_RDONLY, os.ModePerm) if err != nil { panic(err) } buf := make([]byte, 1024) begin := time.Now() for { _, err := fin.Read(buf) if err == io.EOF { break } } fin.Close() fmt.Printf( "read disk orderly %d ms\n" , time.Since(begin).Milliseconds()) } //go test -v go_search_engine/forward_index/serialize -run=TestReadDiskOrderly //为了避免缓存的影响,6个Test函数分6次执行 |
本文来自博客园,作者:高性能golang,转载请注明原文链接:https://www.cnblogs.com/zhangchaoyang/p/15139299.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决