JavaOne总是举行许多有趣的技术会议,但是,今年的JavaOne大会却充满了质量会议;事实上,必须不断举行这些会议以满足大家的需求。developerWorks专栏作者Brian
Goetz从其紧张的日程安排中抽出时间,从性能管理会议中摘录出一些比较典型的概念。
并发工具:
轻松实现多线程
最受欢迎的技术会议之一是Doug Lea关于util.concurrent 并发工具包的讲座。这套广泛使用的并发工具包将构成J2SE
1.5中java.util.concurrent 包的基础,并专门采用JSR
166来说明。
并发工具包的目的在于简单、大胆创新地处理并发应用程序,正如集合框处理数据结构那样。Java语言内置的并发原语——
synchronization , wait 和 notify
——级别较低并且很难使用。因而,我们希望java.util.concurrent 包将具有足够丰富的并发构件块,使大部分服务器端的程序员根本就不必使用wait
和 notify 。
正用来说明java.util.concurrent 包的JSR-166包括:
- 锁定工具类
- 线程池
- 原子变量管理
- 线程协调
- 任务调度
- 信号量
- 互斥
JSR-166还包括若干个新的并发集合类,例如LinkedBlockingQueue
和 ConcurrentHashMap 。为了使履行更加高效灵活,还可以通过更改JVM以支持高性能的比较并交换(compare-and-swap
)操作以及精度为纳秒级的计时。
编程难题
另一场广受欢迎的会议是“编程难题”,两位演讲者Josh
Bloch和Neal Gafter 身着印有Sun标识的工作装,讲演"Click
and Hack, the Type-It Brothers"
。今年,他俩提出了十大编程难题,并图示与以下用途有关的陷阱和常见错觉:
java.math.Random
- 覆盖和重载之间的区别
- 反射API
- 字符编码和区域依赖的不确定性
- 遮盖和隐藏类名
- 静态初始化程序块和final字段的初始化顺序
- 编译器的词法行为
大家与两位演讲者共同度过了一段美好的时光。两位演讲者用他们经典的结束语——“不要象我的兄弟那样编写代码”来结束该场演讲。
基准的魔术(Black
Art of Benchmarking)
“基准的魔术”是一场关于性能调整和管理的优秀会议,由Sun性能管理事业部的Timothy
Cramer、Tom Marble和Menasse Zaudou演讲。该讲座主要针对以下三个领域:
- 编写微基准的难点
- 将性能度量、监控和管理集成到开发和部署周期的重要性
- 如何使用统计方法来有效评估基准数据
众所周知,为Java平台编写微基准很困难,而解释测试结果就更加困难。JIT编译(和代码失效)时间充满了不确定性,这就可能与测试结果有相当大的误差。HotSpot性能参数并不是为了微基准而优化。HotSpot被设计成起动较慢而运行却越来越快,以实现快速起动与快速长期性能之间的平衡,但大多数微基准从不长期运行。由于在开始测量之前有必要先对JIT进行“热身(warm
up)”,从而不能保证足够精确的基准。其原因在于:当新的类被加载时,JVM可能会选择“不优化”或使JIT产生的代码失效,这导致具有相同稳定态性能的两个测试循环出现非常迥异的运行时间,即便在JIT“热身”后情况依然如此。
编写和解释基准的另一个常见错误是,这些基准广泛运行于各种系统和配置之上,并且经常是运行于开发系统而不是目标部属系统之上(以帮助编程决策)。由于处理器、内存或高速缓存配置与开发系统的不同,从而可能导致开发者选择的实现策略比在部属系统上的性能要差。
解释基准结果与构造有效基准一样困难。您不仅要保证您的测试必须重复运行被测代码,而且多次运行有可能返回不同的结果。重要的是,抽取多个样本并使用统计方法以便确定性能是降低还是改善。您可以采用简单的统计测试来确定同一总体的两个样本(这样可以帮助判断代码的改变是否对性能产生影响)是否是“t”测试,这种方法可在任何基础统计测试中找到。确定代码的改变是否会带来性能差异凭“肉眼”难以判断,但使用统计方法就可靠得多。
最后,演讲者们强调将性能度量集成到开发过程以及部属过程中包含including性能监测的重要性。性能目标——不管是等待时间、吞吐量、峰值容量、平均容量或者内存占地面积(footprint)——应该是需求过程的一部分,性能度量应该是测试过程的一部分,而性能监测应该是部属过程的一部分。
打破性能神话
很少有人对JIT内部以及底层Jave性能的了解有Cliff
Click博士(与著名的“Click and Hack”中的“Click”无关)那样多。Cliff
Click博士建构了HotSpot JIT。在“打破性能神话”的演讲中,Click博士提及以下几种常见的性能神话,包括:
- 无竞争的同步(Uncontended
synchronization)速度较慢
- final方法或类可大幅改善JIT内联性
- 异常退出循环可通过避免循环结束测试来改善性能。
- 对象池可大幅度提高性能
Click博士用可靠数据表明,这些陈词滥调不再适用于现代的JVM,并且事实上,其中的某些看法彻底地危害到性能。
如前所述,编写微基准来度量所谓的性能优化效果相当困难,而且很少有人象Click博士那样胜任该工作。Click博士分析了IBM、Intel和Sun公司的七个JVM案例,这些JVM都使用Intel和Sparc平台。
其试验最令人惊讶的结果是,大多数所谓的性能修整并没有任何益处,甚至可能带来严重的危害。与旨在“帮助”JIT或垃圾收集器的令人厌烦的代码相比,符合常规使用模式的整洁代码(clean
code )更适合于现代的JVM。通常那些善意的帮助都会带来不利的后果——破坏许多常规的JIT优化,导致产生更慢而不是更快的代码。由于许多优化都涉及到性能和可维护性之间的平衡,因此,除非可获得显著的长期性能优势,最好偏向于选择可维护性。因为许多常见的性能建议只能改善特殊JVM的性能,因此,调整后的代码可能会改善短期性能,而对于以后的JVM来说,相同的代码可能比“明显”版本("obvious"
version)的代码运行更慢。
Click博士还提及一些不被当前
HotSpot 编译器执行、但可能会被未来版本的 JVM
所采用的优化技术,如漏出分析(确定某个指向对象的指针没有脱离局部上下文,这种情况下,如果其字段可装入寄存器,那么可以在堆中甚或根本就不分配)。虽然有些代码从表面上看对性能来说很耗资源,但是通过高级动态编译器来编译这些代码通常会获得令人惊讶的性能。
参考资料
|