Loading [MathJax]/extensions/MathMenu.js

磁盘是块存储设备,读写连续的一整块磁盘数据其实还是很快的,平时我们感觉磁盘比内存慢是因为没有顺序地读磁盘,而是在随机读,大部分时间都浪费在寻道和旋转上面。

做个试验,对比一下顺序读磁盘和读写内存的速度,看看到底差多少。

试验方法:创建一个长度为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次执行

  

posted on   高性能golang  阅读(485)  评论(0编辑  收藏  举报
编辑推荐:
· 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 重磅开源!
· 字符编码:从基础到乱码解决
点击右上角即可分享
微信分享提示