type
status
date
slug
summary
tags
category
icon
password

overview

处理文件本质上就是将文件内容从磁盘加载到内存中,再进行修改等操作,当文件不大时(比如16MB),我们可以直接将整个文件加载到内存中,当文件大小高达32G时,这种方式显然并不合适。
我们的思路便是将每一次读取到内存中的内容缩小到合适的大小,这样即可完成整个文件的读取。
 
本文分为三部分:
  1. 分片处理,适用于二进制等文件;
  1. 分块处理,适用于文本文件;
  1. 并行处理,可对读取处理的效率进一步优化。
 

分片处理

 
所谓分片,就是指创建一个带有容量的切片,每次对文件都读取切片容量个大小的内容至该切片中处理。
 

分块处理

 
其宗旨是对文本文件按照规定的方式进行分割成块,每一次读取并处理一个块;
 
我们按照以行为分割方式的处理为例:
 
按照代码注释中所讲:标记的规范由类型为SplitFunc的拆分函数定义;
我们可以自定义SplitFunc类型的函数来规定分隔符;
具体可以参考scanner的文档介绍
 

并行优化

 
Go语言具有天然的并发优势,而现代cpu往往是多核,所以可以考虑将程序改为并行处理,这会给我们处理单个大型文件带来性能上的巨大提升;
 
首先思考并行在哪里;
文件处理的流程是读取,然后处理;
在同步模式下,读一块,处理一块,不断循环;
但事实上,在处理一块的时候,完全可以读取下一块,也就是说,下一块的读取与处理和上一块是不相干的;
 
进一步,我们还可以将多个块打包为一组,每次读取部分reader读取完一个组,交给处理部分handler去处理,在此期间无需堵塞,直接读取下一个组中的块,当读完组后,交给另一个handler处理;
于是我们可以设置handler的数目,这个值相当于我们划分出来的组的数量,还可以设置组的大小,也就是一个组包含几个块;
而组的交付则使用channel来进行;
 
而最终,我们还要将多个handler中的处理完成的内容汇总,才能得到最后的结果,于是我们还需要一个combiner;
 
现在,我们考虑好了,整个过程有三大模块:reader,handler,combiner,每一个模块都可以用函数去表示,最终在主函数中产生联系;
 
reader模块代码:
 
handler模块代码
 
combiner模块代码
 
最终实现
 
2023的思考和故事永不存在的与永远存在的
Alex
Alex
某不知名青年|web2.5人士|喜欢猫与美少女
公告
type
status
date
slug
summary
tags
category
icon
password
有事请邮箱联系:alexwu7@outlook.com
🚀🚀🚀