【问题标题】:Inheritance vs code generation for better performance?继承与代码生成以获得更好的性能?
【发布时间】:2020-08-03 10:28:34
【问题描述】:

我正在尝试从一段看起来像这样的代码中获得最大性能

interface DbStream {
    void writeInt(int x);
    void writeString(String s);
    // etc, somewhere around 20 different types
}

interface Writer {
    void write(DbStream stream, Object value);
}

Writer[] writers = new Writer[NUM_COLS];
DbStream stream;
Object[][] src = new Object[NUM_ROWS][NUM_COLS];

for (int row = 0; row < NUM_ROWS; row++) {
    for(int col = 0; col < NUM_COLS; col++) {
        writers[col].write(stream, src[row][col]);
    }
}

Writer 接口的每个实现都进行必要的转换并调用DbStream 的正确方法。该代码使用继承,因此这些调用不是内联的。如果手动展开内部循环以包含对静态方法的 200-300 次调用,是否会提高性能?如果有任何不同,该程序将使用 JDK 13。

【问题讨论】:

  • 您是否验证过您的程序受 CPU 限制?乍一看,你好像在做很多 IO,我希望这会成为瓶颈。我不希望展开循环会产生任何影响。使用分析器查看时间的去向。
  • 过早优化是万恶之源。
  • “代码使用继承,所以这些调用没有内联。”——你真的验证了这个说法吗?

标签: java jvm jit


【解决方案1】:

我正在尝试从一段代码中获得最大性能...

这通常是错误的方法。更好的方法是优化显然是应用程序性能瓶颈的代码。此外,“最大”不是一个好的目标。更好的目标是“足够好”。 (在某种程度上,软件开发人员的时间比 CPU 时间更昂贵。而且它肯定是一种更稀缺的商品!)

我建议你这样做。

  1. 让您的应用程序功能完整并正常工作。

  2. 创建一个实际的基准测试,使用真实数据来测试此代码。

  3. 分析运行基准测试的应用程序,以衡量您的应用程序在这部分代码中花费的时间百分比。

  4. 估计您可以通过优化获得的潜在性能。例如,如果内联这些调用将此代码提高了 10%,并且此代码占应用程序 CPU 总时间的 5%,那么您将通过此优化获得 0.5% 的整体 CPU 性能提升。

  5. 现在决定:

    • 可能/可能的性能提升值得开发工作吗?
    • 对系统可维护性进行(假设的)打击是否值得?
  6. 如果是:进行优化并测量它。

    • 您真的达到了预期的性能吗?
    • 对可维护性的“损害”值得吗?

(如果最小化 CPU 时间不是您的目标,请相应地调整方法。例如,如果您想最小化请求时间,那么您还需要考虑后端数据库所花费的时间等。)


在这种情况下,我的直觉是您提出的优化可能会产生小的性能差异。手动内联调用可以在每次调用中减少一些(比如 3 或 4 条)机器指令。但是,我怀疑这对整体应用程序性能是否重要。

【讨论】:

  • 嗯,这段特殊的代码应该移动 100Tb+ 的数据,这就是我进行微优化的原因。
  • 这不是重点。代码还在工作吗?你做过基准测试吗?你剖析过吗?你能证明(对你的老板说)这是真正的瓶颈所在……并且在这部分花费(比如)一天的开发工作会得到回报吗?
  • 无论哪种方式,如果您要进行优化,那么您需要以一种能让您向自己证明您的努力确实取得了一些成就的方式进行优化。基准、配置文件和前后比较。一些“优化”实际上会使性能变差。
  • 当然我做了一些基准测试和分析,虽然这有点难,因为它涉及两个外部系统并且需要在特定的网络上运行,因此问题。
  • 嗯,你有我的答案。我的直觉是,它会产生很小的影响,但不会很重要。这是任何人都能说的最好的。 (涉及网络,数据库和大量数据的事实都在大声告诉我,这段代码不太可能成为真正的瓶颈。但是......嘿......如果你这么认为...... . 去争取吧。如果结果不是这样,请不要怪我们 :-) )
【解决方案2】:

JDK 规范没有特别承诺性能,也没有规定这两个概念必须发挥作用的方式,这是一个明显的性能漏洞。

换句话说:取决于 JDK 版本、版本、架构、操作系统和月相。

使用JMH 之类的东西来获得实际结果,尽可能接近实际的“现实生活”环境运行它(在相同的硬件上以相似的负载运行它,并确保你测试的代码是尽可能相似)。

鉴于此代码似乎是“写入数据库”,我敢打赌,作为数据库,或者它周围的基础设施(例如制作 TCP 数据包以将它们发送到数据库,即使它在本地运行并且是内存中的实现),将比任何一个慢多个数量级。我预测您的 JMH 结果将非常接近(足够接近以至于您观察到的任何差异都是统计噪声)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-08-18
    • 1970-01-01
    • 1970-01-01
    • 2021-08-27
    • 1970-01-01
    • 1970-01-01
    • 2014-07-22
    相关资源
    最近更新 更多