繁体   English   中英

Java IO性能问题

[英]Java IO Performance Issue

我在用:

PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("test.txt"),1024*1024*500))

写一个大文件(约2GB)。 写入需要26秒。 但是,当我用10/20替换500时,需要19秒。

这里 ,我理解的是缓冲提供了更好的性能。 如果是这样,那么为什么会这样呢? 我通过每次运行5次检查它,因此系统/ IO负载不是问题。

正如我在上一个问题中所说的那样,有一个最佳的缓冲区大小(通常大约为32 KB),当你使缓冲区大于这个时,缓慢而不是更快。 默认缓冲区大小为8 KB。

BTW:您的L2 / L3 CPU缓存有多大? (我怀疑大约10 MB)你的主要L1缓存大约是32 KB?

通过使用适合最快缓存的缓冲区,您使用最快的内存。 通过使用仅适合主存储器的缓冲区,您使用的是最慢的内存(速度慢了10倍)


回答你的问题。

我所做的是假设ISO-8859-1编码即(byte) ch并一次写一个字节到ByteBuffer,可能是内存映射。

我有从ByteBuffer写入/读取longdouble方法,而不会产生任何垃圾。

https://github.com/peter-lawrey/Java-Chronicle/blob/master/src/main/java/vanilla/java/chronicle/impl/AbstractExcerpt.java

使用此方法,您可以每秒向磁盘记录大约500万行。

具有过大的缓冲区会降低性能。 坚持约32-64 kb IMO

1024*1024*500是500兆字节,给予或采取smidgen。 你基本上是强迫JVM分配一个500mb的连续内存块,JVM可能不得不做GC循环。

非常大的缓冲区(500 MB)也不好,因为对于那个巨大的字节缓冲区来说,操作系统更难以进行内存管理。

将它与移动房子中的桌子而不是移动盒子进行比较。 但如果你的盒子变得太小,你将不得不去多次。

不要忘记分配内存是O(n)操作。

首先,你真的不需要一个大的缓冲区。 通常64K甚至低至8K足以获得下降IO性能。 任何更大的,你只是浪费内存和CPU,因为当你越来越大的缓冲区,它花费更多的时间在IO层写入大块数据。 因此,在等待IO和写入内存之间,这是一个权衡(如果你理解微积分,则为最小 - 最大)。 您无法将大缓冲区推送到IO设备,因为它具有内部固定大小的缓冲区。 重点是尝试尽可能地匹配它,但是意识到这样做是相对不可能的,因为你不知道其他处理正在做什么。 最好的办法是尝试低8K-16K的东西,运行它,测量它。 将缓冲区32K等加倍,运行它,测量它。 如果你获得速度提升再做一次。 一旦你停止将速度改进除以2,然后停止。

因此,如果您在26秒内写入2GB数据,那么吞吐量为76MB / S或650Mbit / s。 你可以通过将缓冲区大小降低到合理的水平来改进它。

通过减少系统调用次数,缓冲I / O可以提高性能。 但系统调用并不昂贵(可能是一毫秒左右),过大的缓冲区可能会导致其他区域出现问题。 例如:

  • 500 MB缓冲区使用大量内存,可能会增加GC开销,或者增加系统的分页负载。

  • 如果在一次写入调用中写入500 MB,则写入可能会使系统的缓冲区高速缓存饱和,并且无法在应用程序级别执行其他操作来重叠磁盘写入。

只是尝试使用(显着)较小的缓冲区。 (我个人不会使用大于8kb的缓冲区而不进行一些特定于应用程序的调整。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM