【问题标题】:Obsolete Java Optimization Tips过时的 Java 优化技巧
【发布时间】:2011-04-30 11:17:06
【问题描述】:

Java 编译器废弃了许多性能提示,尤其是Profile-guided optimization。例如,这些平台提供的优化可以极大地(根据来源)降低虚函数调用的成本。 VM 还能够进行方法内联、循环展开等。

还有哪些您发现的其他性能优化技术仍在应用,但实际上已被更现代 JVM 中的优化机制淘汰了?

【问题讨论】:

  • 我在这里有一个相关问题的赏金,如果有人引用这个问题的答案:stackoverflow.com/questions/3963643/…
  • 我认为这个问题有缺陷,因为它取决于您使用的编译器
  • @Raul,欢迎提供编译器特定信息...
  • 我搜索了它@Dan...但从实际的角度来看,这不是一个失败提示问题,所以没有很多信息可用

标签: java performance optimization


【解决方案1】:

方法和方法参数的 final 修饰符对性能没有任何帮助。

此外,Java HotSpot wiki 很好地概述了 HotSpot 使用的优化以及如何在 Java 代码中有效地使用它们。

【讨论】:

  • 不错的链接,但它似乎并没有消除final。它说'final'是对内联的暗示。我认为在某些情况下 final 修饰符会向编译器保证它的值不能在循环中改变,即使该循环调用其他方法并且超出当前范围。
  • final 关于方法(或与此相关的类)不向 JIT 提供任何信息。但是,方法参数上的final 可以很好地提供有用的优化提示(类似于声明为 final 的局部变量)。不过,最终使用 final 的原因是为了强制保持不变性——这是一种设计时特性,可以使代码更易于维护。任何优化好处都需要 a) 只担心是否真的存在性能问题,并且 b) 进行详尽的测试以确保它确实有所作为。
  • 实际上,final 在参数上通常不会有任何区别(编译器确实可以看到您是否分配给它,并且 Java 不会通过引用传递变量 - 对象通过引用传递,但持有它们的变量不会)但是这确实意味着该参数可以与内部类或匿名类一起使用。如果有意义就使用,否则不要。
  • 我使用 final 作为确保类不变性的一种方式。通常作为私有最终字段。我还使用它来确保我不会更改传递参数的值/引用。换句话说,我只是将其用于正确性而非优化。
  • 我不会在方法参数或方法变量上使用 final 来优化任何东西,我将其用作编码练习,以便开发人员可以看到这个值确实没有改变。任何优化都是其次的。
【解决方案2】:

人们用多次调用 StringBuilder 或 StringBuffer 来替换 String a = "this" + var1 + " is " + var2;。它实际上已经在幕后使用了 StringBuilder。

【讨论】:

  • 在这种情况下,我相信优化仍然适用。您展示的示例代码将构建 3 个不同的 StringBuilder 实例,每个连接一个;只建造一个会(稍微)更有效率。如果我错了,请纠正我。
  • 哦,我以为它会相当于String a = new StringBuilder("this").append(var1).append("is").append(var2).toString();
  • this unauthoriative source rgagnon.com/javadetails/java-0129.html 建议 Paul 对单个 StringBuilder 的看法是正确的,但表示 StringBuilder 的默认容量可能太短(奇怪,这对于花时间使用 StringBuffer 的编译器不会费心在使用前计算容量)
  • 在一行上完成字符串连接时,使用 StrinBuilder 不会增加任何内容。但是,用 StringBuilder 替换这个:String a = "this" + var1; a += " is " + var2; 仍然有效。 (至少这是我最后一次检查:-/)
  • @Devon,我认为你是对的,因为在多行上这样做会涉及创建一堆不同的 String 对象。
【解决方案3】:

在开始性能优化之前,有必要定义时间/内存权衡。这就是我为我的内存/时间关键型应用程序做的事情(重复上面的一些答案,以完成):

  1. 规则 #1 永远不要在开发的早期阶段进行性能优化。 如果您真的不需要,永远不要这样做。如果决定这样做,那么:
  2. 使用profiler查找瓶颈,查看源码查找瓶颈原因;
  3. 选择最适合定义的时间/内存权衡的适当数据结构;
  4. 选择合适的算法(例如迭代与递归等);
  5. 如果您真的不需要,请避免使用 java 库中的同步对象;
  6. 避免显式/隐式创建新对象;
  7. 当且仅当您确定它们不符合您的要求时,覆盖/重新实现 java 附带的数据类型/算法。
  8. 使用小型独立测试来测试所选算法/数据结构的性能。

【讨论】:

  • 这些技巧并没有真正过时。我的意思是,这是一个绝妙的建议,但你没有回答这个问题。
  • 为了缓解规则 1,有些东西易于编写和易于阅读,任何体面的软件工程师都应该知道并立即正确执行,例如在链表和数组列表之间进行选择.这是免费的,以后可以避免头痛。也就是说,本质上是好的软件设计。
【解决方案4】:

2001 年,我为 J2ME 手机制作了应用程序。它有一块砖那么大。并且非常接近砖块的计算能力。

要让 Java 应用程序在其上以可接受的方式运行,需要以尽可能程序化的方式编写它们。此外,非常大的性能改进是捕获ArrayIndexOutOfBoundsException 以退出向量中所有项目的for循环。考虑一下!

即使在 Android 上,也有“快速”循环遍历数组中的所有项目和“慢速”编写相同内容的方式,如 dalvik VM 内部的 Google IO 视频中所述。

但是,在回答您的问题时,我想说的是,如今必须对这类事情进行微优化是最不寻常的,我进一步希望在 JIT VM(甚至是新的 Android 2.2 VM ,这增加了 JIT)这些优化没有实际意义。 2001 年,这款手机以 33MHz 运行 KVM 解释器。现在它运行 dalvik - 一个比 KVM 快得多的 VM - 在 500MHz 到 1500MHz 上运行,具有更快的 ARM 架构(更好的处理器甚至允许时钟速度增益)和 L1 等。 JIT 到达。

我们还没有进入我可以在 Java 中进行直接像素操作的领域——无论是在手机上还是在带有 i7 的桌面上——所以仍然有普通的日常代码,Java 并不快够了。 Here's an interesting blog 声称一位专家表示,对于一些繁重的 CPU 任务,Java 是 C++ 速度的 80%;我持怀疑态度,我编写了图像处理代码,我发现 Java 和本机 for 像素循环之间存在一个数量级。也许我错过了一些技巧......? :D

【讨论】:

  • 有点 OT,但在性能方面,我的一个朋友用 Java 创建了一个源代码忠实的 Doom 端口,它在单线程 P4 上以 640x480 分辨率获得大约 130-145 FPS @ 3GHz。不是 OpenGL,只是 blitting。
  • 是的,但我在 486 上玩《毁灭战士》还算可以接受……(不过,你朋友的项目听起来很有趣也很酷)
【解决方案5】:
  1. 不要手动调用垃圾收集器,这会损害现代 JVM 实现的性能。
  2. 整数而不是 Long 不会节省太多空间,但会限制数字的范围。
  3. 避免手动生成 Enum 类,而是使用内置的 Enum。 Java 1.5 引入了真正的枚举,使用它们。

【讨论】:

    【解决方案6】:

    使用 RAM 小于 32GB 的 x64 JVM 时

    与 32 位 JVM 相比,64 位 JVM 使用的内存多 30%-50%,因为普通对象指针更大。你可以通过使用 JDK6+ 来大大减少这个因素。

    从 JDK6u6p 到 JDK6u22 是可选的,可以通过添加 JVM 参数来启用:

    -XX:+UseCompressedOops 
    

    从 JDK6u23(JDK7 也是)默认启用。更多信息here

    【讨论】:

      【解决方案7】:
      1. “过早的优化是万恶之源”(Donald Knuth)
      2. 只优化瓶颈很有用。
      3. 您应该在每种情况下分析代码。也许您可以用快速的 HashSet 替换 TreeSet,因为您不需要排序功能,或者您可以使用 float 而不是 double(查看 Android SDK)。
      4. 如果没有任何技术可以帮助您,您可以尝试重写一段代码并通过JNI 调用它,这样本机代码就可以工作了。

      【讨论】:

      • -1 表示既不完整又与问题无关的报价。 Donald Knuth 说:“我们应该忘记小的效率,说大约 97% 的时间:过早优化是万恶之源”其次,问题是关于不再适用的一般优化技术,没有什么可以证明它是为时过早,这是一个一般性讨论
      【解决方案8】:

      我发现上面的链接已经过时了。这里有一篇关于 Java 优化的新文章:http://www.appperfect.com/support/java-coding-rules/optimization.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-11-10
        • 1970-01-01
        • 1970-01-01
        • 2012-08-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多