栏目导航
热点推荐
- 三十条有用的 Java 编程规则
- Java制作水印图片源码
- Java常见异常及可能的导致原因
- Java中的修饰词使用方法总结
- J2EE系统异常的处理准则
- Java中的异常、断言、日志解析(
- Java面试技巧:Java面试题集锦(
- 面向Java开发人员的Scala指南:
- Java程序员:一刻钟精通正则表达
- 网友经验分享:学好java开发的关
- 专家解答:创建表格与数据库进行
- Java远程访问Domino数据库
阅览排行
使用实时Java降低Java应用程序的易变性(3)
www.jz123.cn 2010-10-22 来源: 中国建站 责任编辑(袁袁) 我要投递新闻
由于我们的 GCStressThread 生成了一个不断变化的活动数据集,所以使用分代 GC 策略并不能提供太多暂停时间优势。相反,我们尝试使用 IBM WebSphere Real Time for Real Time Linux V2.0 SR1 产品中的实时垃圾收集器。最初的结果令人失望,甚至在添加了 -Xgcthreads8 选项之后也是如此,该选项允许收集器使用 8 个 GC 线程,而不是默认的 1 个线程。(使用一个 GC 线程,收集器无法可靠地跟上此应用程序的分配速度)。
$ java -Xms700m -Xmx700m -Xgcpolicy:metronome -Xgcthreads8 Server 6 10000 operations in 72024 ms Throughput is 138 operations / second Histogram of operation times: 11ms - 12ms 82 0 % 12ms - 13ms 250 2 % 13ms - 14ms 19 0 % 14ms - 15ms 50 0 % 15ms - 16ms 339 3 % 16ms - 17ms 889 8 % 17ms - 18ms 730 7 % 18ms - 19ms 411 4 % 19ms - 20ms 287 2 % 20ms - 30ms 1051 10 % 30ms - 40ms 504 5 % 40ms - 50ms 846 8 % 50ms - 60ms 1168 11 % 60ms - 70ms 1434 14 % 70ms - 80ms 980 9 % 80ms - 90ms 349 3 % 90ms - 100ms 28 0 % 100ms - 112ms 7 0 % |
使用实时收集器显着缩短了最大操作时间,但是同时也增加了操作时间跨度。更糟的是,吞吐率大大降低。
最后一步是为工作者线程使用 RealtimeThread,而不是常规 Java 线程。我们创建一个 RealtimeThreadFactory 类,我们可以将该类提供给 Executors 服务,如清单 10 所示:
清单 10. RealtimeThreadFactory 类
import java.util.concurrent.ThreadFactory; import javax.realtime.PriorityScheduler; import javax.realtime.RealtimeThread; import javax.realtime.Scheduler; import javax.realtime.PriorityParameters; class RealtimeThreadFactory implements ThreadFactory { public Thread newThread(Runnable r) { RealtimeThread rtThread = new RealtimeThread(null, null, null, null, null, r); // adjust parameters as needed PriorityParameters pp = (PriorityParameters) rtThread.getSchedulingParameters(); PriorityScheduler scheduler = PriorityScheduler.instance(); pp.setPriority(scheduler.getMaxPriority()); return rtThread; } } |
如果将 RealtimeThreadFactory 类的一个实例传递给 Executors.newFixedThreadPool() 服务器,将导致工作者线程变为使用具有最高优先级的 FIFO 调度机制的 RealtimeThread。垃圾收集器仍然会在需要执行工作时中断这些线程,但其他较低优先级任务不会干扰工作者线程:
$ java -Xms700m -Xmx700m -Xgcpolicy:metronome -Xgcthreads8 Server 6 Handled 10000 operations in 27975 ms Throughput is 357 operations / second Histogram of operation times: 11ms - 12ms 159 1 % 12ms - 13ms 61 0 % 13ms - 14ms 17 0 % 14ms - 15ms 63 0 % 15ms - 16ms 1613 16 % 16ms - 17ms 4249 42 % 17ms - 18ms 2862 28 % 18ms - 19ms 975 9 % 19ms - 20ms 1 0 % |
通过此更改,我们显着改善了最差的操作时间(降低到 19 毫秒)和总吞吐量(提升到每秒 357 个操作)。所以我们显着改善了操作时间的易变性,但是在吞吐量性能上付出了昂贵的代价。垃圾收集器的操作(使用每 10 毫秒中的至多 3 毫秒)解释了为什么通常需要约 12 毫秒的操作可改善至 4 - 5 毫秒,这也是大量操作现在需要花 16 - 17 毫秒时间的原因。吞吐量的下降可能比预期更严重,因为除了使用 Metronome 垃圾收集器,实时 JVM 还修改了预防优先级反转的锁定原语,优先级反转是使用 FIFO 调度时的一个重要问题。不幸的是,主线程与工作者线程之间的同步导致了最终影响吞吐量的大量开销,但是我们没有将其作为任何操作时间的一部分来进行测量(所以没有在直方图中显示)。
所以,尽管我们在服务器中通过修改改善了可预测性,但它的吞吐量明显降低。但是,如果将少数很长的操作时间当作不可接受的服务质量水平,那么使用 RealtimeThread 和实时 JVM 可能是正确的解决方案。
结束语
在 Java 应用程序领域,吞吐量和延迟是应用程序和基准测试设计师选择用于报告和优化的传统指标。这种选择对构建用于改善性能的 Java 运行时具有广泛影响。尽管 Java 运行时已成为具有极慢的运行时延迟和极低的吞吐量的解释器,但现在对于许多应用程序,JVM 仍然可以在这些指标上与其他语言抗衡。但是,直到最近,这种观点不再适合一些可能对应用程序的已知性能产生极大影响的其他指标,尤其是会影响服务质量的易变性。
实时 Java 的引入为应用程序设计师提供了必要的工具来解决 JVM 和应用程序中的易变性源头,从而交付消费者和客户期望的服务质量。本文介绍了许多技术,您可以使用它们修改 Java 应用程序,以减少源自于 JVM 和线程调度的暂停和易变性。减少易变性通常会增加延迟时间和降低吞吐量性能。可接受的降低程度取决于适用于特定应用程序的工具。
上一篇:使用实时Java降低Java应用程序的易变性(2) 下一篇:Java5:BigInteger、BigDecimal详解