高效读取大文件,再也不用担心 OOM 了!(上)

简介: 最近阿粉接到一个需求,需要从文件读取数据,然后经过业务处理之后存储到数据库中。这个需求,说实话不是很难,阿粉很快完成了第一个版本。

内存读取

第一个版本,阿粉采用内存读取的方式,所有的数据首先读读取到内存中,程序代码如下:

Stopwatch stopwatch = Stopwatch.createStarted();
// 将全部行数读取的内存中
List<String> lines = FileUtils.readLines(new File("temp/test.txt"), Charset.defaultCharset());
for (String line : lines) {
    // pass
}
stopwatch.stop();
System.out.println("read all lines spend " + stopwatch.elapsed(TimeUnit.SECONDS) + " s");
// 计算内存占用
logMemory();

logMemory方法如下:

MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
//堆内存使用情况
MemoryUsage memoryUsage = memoryMXBean.getHeapMemoryUsage();
//初始的总内存
long totalMemorySize = memoryUsage.getInit();
//已使用的内存
long usedMemorySize = memoryUsage.getUsed();
System.out.println("Total Memory: " + totalMemorySize / (1024 * 1024) + " Mb");
System.out.println("Free Memory: " + usedMemorySize / (1024 * 1024) + " Mb");

上述程序中,阿粉使用 Apache Common-Io 开源第三方库,FileUtils#readLines将会把文件中所有内容,全部读取到内存中。

这个程序简单测试并没有什么问题,但是等拿到真正的数据文件,运行程序,很快程序发生了 OOM

之所以会发生 OOM,主要原因是因为这个数据文件太大。假设上面测试文件 test.txt总共有 200W 行数据,文件大小为:740MB。

通过上述程序读取到内存之后,在我的电脑上内存占用情况如下:44.jpg

可以看到一个实际大小为 700 多 M 的文件,读到内存中占用内存量为 1.5G 之多。而我之前的程序,虚拟机设置内存大小只有 1G,所以程序发生了 OOM。

当然这里最简单的办法就是加内存呗,将虚拟机内存设置到 2G,甚至更多。不过机器内存始终有限,如果文件更大,还是没有办法全部都加载到内存。

不过仔细一想真的需要将全部数据一次性加载到内存中?

很显然,不需要!

在上述的场景中,我们将数据到加载内存中,最后不还是一条条处理数据。

所以下面我们将读取方式修改成逐行读取。

相关文章
《C++避坑神器·七》二进制读写自定义类型导致崩溃或数据读写不全问题
《C++避坑神器·七》二进制读写自定义类型导致崩溃或数据读写不全问题
106 0
|
SQL 缓存 监控
掌握了这些优化技巧,再也不用担心接口性能上不去了!
优化接口性能对每个后端开发同学来说见惯不惯了,也是一项必备的技能,因为我们平时开发中都会对外提供接口,性能差的话,功能多少会有影响。
|
C++
40.【C++最全文件操作,少一个你打我】(一)
40.【C++最全文件操作,少一个你打我】
82 0
|
C++
40.【C++最全文件操作,少一个你打我】(二)
40.【C++最全文件操作,少一个你打我】
46 0
|
Java
项目实战典型案例20——内存长期占用导致系统慢
项目实战典型案例20——内存长期占用导致系统慢
92 0
【项目实战典型案例】20.内存长期占用导致系统慢
【项目实战典型案例】20.内存长期占用导致系统慢
|
存储 缓存 文件存储
「系统」占用太多硬盘空间?试试用这些方法将它找回来
「系统」占用太多硬盘空间?试试用这些方法将它找回来
340 0
|
存储 消息中间件 Linux
看完这篇文章,我再也不用担心线上出现 CPU 性能问题了(上)
生产环境上出现 CPU 性能问题是非常典型的一类问题,往往这个时候就比较考验相关人员排查问题的能力
|
IDE Linux 调度
看完这篇文章,我再也不用担心线上出现 CPU 性能问题了(下)
在上一篇文章中咸鱼给大家介绍了 CPU 常见的性能指标,当生产环境出现 CPU 性能瓶颈的时候,优先观察这些指标有没有什么异常的地方,能解决大部分情况
|
存储 缓存 PHP
关于文件上传如何避免垃圾文件产生的程序设计思路
上传文件的时候,现在图片文件上传至缓存目录,返回链接,回显。在点击提交写入数据库的时候,将写入数据库的那个图片链接对应的图片移动到正式的图片目录下。然后写个定时任务,定期去清除缓存目录中的文件。这样就会避免垃圾文件的产生了~
681 0
关于文件上传如何避免垃圾文件产生的程序设计思路