我正在对我的类进行一些Java性能比较,并想知道是否有某种Java性能框架可以使编写性能测量代码更容易?
即,我现在正在尝试测量的是,与使用AtomicInteger作为我的“同步器”相比,PseudoRandomUsingSynch.nextInt()中的方法具有“同步”效果。
所以我试图测量使用3个线程生成随机整数所需的时间,这些线程访问同步方法循环10000次。
我相信有更好的方法可以做到这一点。能请你赐教吗? :)
public static void main( String [] args ) throws InterruptedException, ExecutionException {
PseudoRandomUsingSynch rand1 = new PseudoRandomUsingSynch((int)System.currentTimeMillis());
int n = 3;
ExecutorService execService = Executors.newFixedThreadPool(n);
long timeBefore = System.currentTimeMillis();
for(int idx=0; idx<100000; ++idx) {
Future<Integer> future = execService.submit(rand1);
Future<Integer> future1 = execService.submit(rand1);
Future<Integer> future2 = execService.submit(rand1);
int random1 = future.get();
int random2 = future1.get();
int random3 = future2.get();
}
long timeAfter = System.currentTimeMillis();
long elapsed = timeAfter - timeBefore;
out.println("elapsed:" + elapsed);
}
班级
public class PseudoRandomUsingSynch implements Callable<Integer> {
private int seed;
public PseudoRandomUsingSynch(int s) { seed = s; }
public synchronized int nextInt(int n) {
byte [] s = DonsUtil.intToByteArray(seed);
SecureRandom secureRandom = new SecureRandom(s);
return ( secureRandom.nextInt() % n );
}
@Override
public Integer call() throws Exception {
return nextInt((int)System.currentTimeMillis());
}
}
此致
答案 0 :(得分:12)
忽略微基准标记在你的情况下是否有用的问题(斯蒂芬C的观点非常有效),我会指出:
首先,不要听那些说'不是那么难'的人。是的,使用JIT编译的虚拟机上的微基准测试很困难。实际上很难从微基准测试中获得有意义和有用的数据,并且任何声称它并不难的人要么是超天才,要么是做错了。 :)
其次,是的,有一些这样的框架。一个值得关注的(认为它处于早期发布前阶段)是Caliper,由Kevin Bourrillion和Google的Jesse Wilson撰写。从早期的一些看起来真的令人印象深刻。
答案 1 :(得分:8)
更多微基准测试建议 - 微基准测试很少告诉您真正需要知道的内容......实际应用程序的运行速度有多快。
在您的情况下,我想您正试图弄清楚您的应用程序是否会使用Atomic对象比使用synchronized更好......反之亦然。真正的答案是它很可能取决于微基准无法衡量的因素。诸如争用的可能性,持有锁的时间,线程和处理器的数量,以及使原子更新成为可行解决方案所需的额外算法工作量。
编辑 - 回答这个问题。
那么有没有办法可以衡量所有这些争用概率,锁定持续时间等等?
理论上是的。一旦实现了整个应用程序,就可以对其进行检测以测量这些内容。但这也没有给你答案,因为没有预测模型你可以插入这些数字来给出答案。此外,您已经实施了该应用程序。
但我的观点并不是衡量这些因素可以让你预测表现。 (事实并非如此!)而是,微基准 不允许
实际上,最好的方法是根据你的直觉实现应用程序,然后使用分析作为确定真正性能问题所在的基础。
答案 2 :(得分:4)
这些人设计了一个很好的JVM测量方法,所以你不会用伪造的数字欺骗自己,然后把它作为Python脚本发布,这样你就可以重用他们的智慧 -
Statistically Rigorous Java Performance Evaluation (pdf paper)
答案 3 :(得分:4)
OpenJDK的人开发了一个名为JMH的基准测试工具:
http://openjdk.java.net/projects/code-tools/jmh/
这提供了一个非常容易设置的框架,并且有几个示例显示了如何使用它。
没有什么可以阻止你编写基准测试错误,但他们在消除非明显错误(例如线程之间的错误共享,防止死代码消除等)方面做得很好。
答案 4 :(得分:3)
您可能希望将循环移动到任务中。因为它只是启动所有线程,几乎立即你回到单线程。
通常的微基准测试建议:允许一些热身。除了平均值,偏差也很有趣。使用System.nanoTime
代替System.currentTimeMillis
。
具体到这个问题是线程打了多少。对于大量竞争线程,cas循环可以执行浪费的工作。创建SecureRandom
可能很昂贵,因此可能System.currentTimeMillis
的程度较低。我相信如果使用正确,SecureRandom
应该已经是线程安全的。
答案 5 :(得分:1)
简而言之,您正在寻找“Java单元性能测试工具”?
使用JUnitPerf。
更新:对于尚不清楚的情况:它还支持并发(多线程)测试。以下是上述链接“LoadTest”一章的摘录,其中包含代码示例:
例如,要创建负载测试 每个用户10个并发用户 跑了 ExampleTestCase.testOneSecondResponse() 20次迭代的方法,并用1 加入之间的第二次延迟 用户,使用:
int users = 10; int iterations = 20; Timer timer = new ConstantTimer(1000); Test testCase = new ExampleTestCase("testOneSecondResponse"); Test repeatedTest = new RepeatedTest(testCase, iterations); Test loadTest = new LoadTest(repeatedTest, users, timer);