【问题标题】:Java IO Performance IssueJava IO 性能问题
【发布时间】:2012-04-13 15:12:35
【问题描述】:

我正在使用:

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

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

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

【问题讨论】:

标签: java


【解决方案1】:

正如我在上一个问题中所说,有一个最佳缓冲区大小(通常约为 32 KB),当您使缓冲区大于此大小时,它会变慢而不是变快。默认缓冲区大小为 8 KB。

顺便说一句:您的 L2/L3 CPU 缓存有多大? (我怀疑大约 10 MB)您的主 L1 缓存大约是 32 KB?

通过使用适合最快缓存的缓冲区,您正在使用最快的内存。通过使用仅适合主内存的缓冲区,您正在使用最慢的内存(慢 10 倍)


回答你的问题。

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

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

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

使用这种方法,您可以每秒将大约 500 万行记录到磁盘。

【讨论】:

  • 另一个不错的答案。谢谢。能否告知,PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("compresedchr1.txt"),32KB)); out.print(char) - 哪个 nio 函数替换了这个?那一个更快吗?或者任何其他写 char 的方式?
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    1024*1024*500 是 500 兆字节,给或取一点点。您基本上是在强制 JVM 分配一个 500mb 的连续内存块,而 JVM 可能必须执行一个 GC 循环来执行此操作。

    【讨论】:

    • 没有没有。我有 16 GB 内存。 JVM 分配了 5/6 GB。我认为没有 GC 循环。
    【解决方案4】:

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

    将其与在您的房子里移动一张桌子而不是移动一个盒子进行比较。但如果你的箱子太小,你就得来来回回很多次了。

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

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

        【解决方案6】:

        缓冲 I/O 可以通过减少系统调用的数量来提高性能。但是系统调用并没有那么昂贵(可能是一毫秒左右),过大的缓冲区可能会导致其他方面的问题。例如:

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-12-06
          • 2014-08-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-08
          • 1970-01-01
          相关资源
          最近更新 更多