Java并发编程——测试并发程序

1、测试正确性

为并发类创建有效的安全测试,其挑战在于:如何在程序出现问题并导致某些属性极度可能失败时,简单地识别出这些受检查的属性来,同时不要认为地让查找错误的代码限制住程序的并发性。最好能做到在检查测试的属性时,不需要任何同步。

测试应该在多处理器系统上运行,以提高潜在交替运行的多样性。但是,多个CPU未必会使测试更加高效。为了能够最大程度地检测到时序敏感的数据竞争的发生机会,应该让测试中的线程多于CPU数,这样在任何给定的时间里,都有一些线程在运行,一些被交换出执行队列,这样可以增加线程间交替行为的随机性。   

2、测试性能

与活跃度测试 相关的是性能测试。性能测试可以通过很多方式来测量,其中包括:吞吐量、响应性和可伸缩性。

3、避免性能测试的陷阱

1)垃圾回收

两种策略可以避免垃圾回收对你的结果带来的误差。第一种策略,确保在测试运行的整个期间,垃圾回收根本不会执行(通过调用JVM时使用-verbose:gc可以做到);另一种策略是,你能确保执行测试期间垃圾回收器运行多次,这样测试程序能够充分反映出运行期间的分配与垃圾回收的开销。后一种策略更佳——它需要更长的测试时间,并且更可能反映现实环境下的性能。  

2)动态编译

时序测试应该在所有代码编译完成后再运行;测量解释执行的代码速度是没有意义的,因为多数程序运行德足够长后,所有频繁执行的代码路径都会被编译。

允许编译器可以在测试期间运行,会带来测试结果偏差:编译消耗CPU资源,所得性能指标没有很大的意义。 

3)代码路径的非真实取样

动态编译会针对一个纯粹的单线程化的测试程序,进行一些专门的优化。只要一个真实的应用程序中包含了一点偶发的并行,这种优化就不会出现在该程序中。

4)不切实际的竞争程度

并发性能测试,除了需要考虑协调并发的因素,应该尽量去模拟让线程本地的计算由某一个特有的应用程序来完成。如果每个任务在真实应用程序中完成的工作,与测试程序相比,其本质和范围有相当大的不同,那么得到的关于性能瓶颈位置结论将是毫无依据的。

5)死代码的消除

编写有效的性能测试,就需要哄骗优化器不要把你的基准测试当作死代码而优化掉。这需要每一个计算的结果都要应用在你的程序中——以一种不需要的同步或真实计算的方式。      

4、测试方法补漏

代码审查和静态分析工具



留言