Go语言中IO与缓冲的深度解析

发表时间: 2024-07-27 07:34

自行实现BufferedWriter,我实现了一个BufferedWriter,速度提升了9倍。

有V/O的地方就有缓冲,缓冲是如此的重要,所以在课程里面会自己实现一个BufferedWriter,一方面可以用来练手,另一方面可以了解一下缓冲的实现细节。

第三点通过做测试可以直观的感受一下使用缓冲和不使用缓冲在速度上有多大差别。缓冲就类似于要从北京向天津发快递,发一个快递也是需要一辆面包车,发一百个快递也是需要一辆面包车,所以不如攒够100件再一起发送。

代码设计如图所示,这里面很核心的是用到了buffer,这是一个byte切片。

·第一次想把5个字节写到磁盘里面去,写到文件里面去,只是把它写入到了buffer切片里面去,并没有真正的去写磁盘。

·第二次要把绿色的内容写文件,同理只是把它追加到了bufferbyte切片里面去。

·第三次还是只写切片,没有写磁盘。

·如果第四次写入发现buffer已经容不下新内容了,这个时候才会触发真正的写磁盘。

据说会有一个变量buffer end index,通过这个变量来标记一下目前buffer已经写到哪个位置了。每次需要刷磁盘直接从开始位置一直到buffer end index,这个位置的内容全部写入磁盘。写磁盘之后立马把buffer end index置为0,置到最开始的位置,这样新的内容再次往buffer里面写的时候就是从endindex开始往后写。

看一下代码实现,这边BufferedFileWriter是一个结构体,里面三个核心的成员变量。

·第一个是buffer缓冲切片。

·第二个end inbex用来记录当前buffer已经写到哪个位置。

·第三个一个文件句柄指向底层的文件。

核心函数要把content写到文件里面去,核心是先判断一下content的长度加上目前所在的end index位置有没有超过缓冲的总容量。如果超过了,就需要Flush刷磁盘。

这个刷磁盘核心分为两步。

·第一步是需要把buffer里面从for1:=0;1<len(src)这个位置的内容全部写到底层的文件磁盘里面去。

·然后紧接着把end index置为0。

·刷磁盘之后再把content内容、新内容追加到buffer后面去,也就是追加到end index往后的位置里面去。

·然后立即把end index进行后移、移动。

这么多位置刚好是content的长度。这边简单测试了一下,把一个字符串往文件里面写10万次,一种是不用缓冲直接写,一种是使用刚才实现的buffered FileWriter往里面写10万次。不用缓冲耗时155ms,用缓冲仅需要17毫秒,差不多速度上快了9倍。

关注《go语言编程大全》,了解更多I0优化的底层原理。