【问题标题】:Maximising Java application (vanilla data processing) performance最大化 Java 应用程序(普通数据处理)性能
【发布时间】:2016-09-02 15:28:44
【问题描述】:

我不是第一次遇到这个问题。

我通过查看 Java Mission Control 中的 Flight Recorder 记录来优化我的 Scala / Java 代码。查看最热门的方法,然后是内存分配,最终应用程序的运行速度提高了 50 倍或 3 倍。

当我达到这一点时,CPU 使用率为 60-90%,内存使用量是最大 4GB 堆中的 2GB。但我认为我可以提高速度。

特点:

  • 单线程处理,从文件系统中读取单个文件。
  • 文件系统读取速度为 1GB/s,但处理速度低至 5MB/s(分支、状态机等)的顺序读取。
  • 尽可能减少垃圾收集。
  • 没有花哨的库,只有纯 JVM 代码。

代码大致如下(伪代码):

for line in file // using an iterator which would call into a file
  result = process_line(line)
  state = state.process(result)
  if state.emits:
    println(state.result)

在一个应用程序中,我有以下最热门的方法:

scala.collection.immutable.HashMap$HashTrieMap.getO(Object, Int, Int)  6.75%
java.io.BufferedInputStream.read() 4.97% 

在另一个(这不是我的想法):

(some sort of garbage collection process) 9%
...       7%

还值得优化这些吗?我已经尝试过,但对于更复杂的代码,性能几乎没有提升。

接下来我应该看哪里?

我是否应该考虑在一个线程上执行process_line(),然后在另一个线程上迭代状态以最小化上下文切换?也许这就是让事情变慢的原因?

什么是正确的方法?我还不想将问题本身并行化。

【问题讨论】:

  • 我会专注于你花费最多时间使用 CPU 的地方,看看你是否可以优化它或将工作传递给另一个线程。 IE。你正朝着正确的方向前进,你需要不断优化。
  • 我更新了问题以包含更多细节。没有“最热门”的方法,有一堆来自不同软件包的使用大致相似数量的 CPU。
  • 我会怀疑像你这样的排序集合,看看你是否可以在没有它的情况下编写代码。 BufferedInputStream.read() 不应该那么昂贵,因为理想情况下它应该一次读取阻塞字节,但这取决于你为什么这样做。我会看看有多少方法是“噪音” esp 收集操作,而不是你的应用程序的核心逻辑。
  • 如果您担心上下文切换的成本,您应该对其进行衡量。以及其他操作系统级别的统计信息以及它们。既然你在做 println,你有没有试过重定向到/dev/null
  • @the8472 不打印任何输出会产生 8% 的性能提升。您将如何测量 Mac / Linux 上的此类上下文切换?

标签: java performance scala optimization jvm


【解决方案1】:

我会并行化阅读器。

如果数据在磁盘上,您可以创建一个线程以块的形式从磁盘读取数据,并创建另一个线程来处理它。顺便说一下,这就是 Java Mission Control 4 读取记录文件的方式。或者您可以像 Java Mission Control 5 那样使用从多个线程读取的 RandomAccessFile,然后将结果拼接在一起。

【讨论】:

    猜你喜欢
    • 2021-08-09
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多