简体   繁体   English

Java性能测量

[英]Java Performance measurement

I am doing some Java performance comparison between my classes, and wondering if there is some sort of Java Performance Framework to make writing performance measurement code easier? 我正在我的类之间进行一些Java性能比较,并想知道是否有某种Java性能框架可以使编写性能测量代码更容易?

Ie, what I am doing now is trying to measure what effect does it have having a method as "synchronized" as in PseudoRandomUsingSynch.nextInt() compared to using an AtomicInteger as my "synchronizer". 也就是说,我现在正在尝试测量的是,与使用AtomicInteger作为我的“同步器”相比,PseudoRandomUsingSynch.nextInt()中的方法具有“同步”的效果。

So I am trying to measure how long it takes to generate random integers using 3 threads accessing a synchronized method looping for say 10000 times. 因此,我试图测量使用3个线程访问同步方法循环10000次的生成随机整数所需的时间。

I am sure there is a much better way doing this. 我相信有更好的方法可以做到这一点。 Can you please enlighten me? 能请你赐教吗? :) :)

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);
}

the class 班级

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());
}
}

Regards 问候

Ignoring the question of whether a microbenchmark is useful in your case (Stephen C' s points are very valid), I would point out: 忽略一个微基准标记在你的情况下是否有用的问题(斯蒂芬C的观点非常有效),我想指出:

Firstly, don't listen to people who say 'it's not that hard'. 首先,不要听那些说“不是那么难”的人。 Yes, microbenchmarking on a virtual machine with JIT compilation is difficult. 是的,使用JIT编译的虚拟机上的微基准测试很困难。 It's actually really difficult to get meaningful and useful figures out of a microbenchmark, and anyone who claims it's not hard is either a supergenius or doing it wrong. 实际上很难从微基准测试中获得有意义和有用的数据,并且任何声称它并不难的人要么是超天才,要么是做错了。 :) :)

Secondly, yes, there are a few such frameworks around. 其次,是的,有一些这样的框架。 One worth looking at (thought it's in very early pre-release stage) is Caliper , by Kevin Bourrillion and Jesse Wilson of Google. 一个值得关注的(认为它是在很早的发布前阶段)是Caliper ,由Kevin Bourrillion和谷歌的Jesse Wilson。 Looks really impressive from a few early looks at it. 从早期的一些看起来真的令人印象深刻。

More micro-benchmarking advice - micro benchmarks rarely tell you what you really need to know ... which is how fast a real application is going to run. 更多微基准测试建议 - 微基准测试很少告诉您真正需要知道的内容......实际应用程序的运行速度有多快。

In your case, I imagine you are trying to figure out if your application will perform better using an Atomic object than using synchronized ... or vice versa. 在您的情况下,我想您正试图弄清楚您的应用程序使用Atomic对象的性能是否优于使用synchronized ...或反之亦然。 And the real answer is that it most likely depends on factors that a micro-benchmark cannot measure . 真正的答案是, 它很可能取决于微基准无法衡量的因素 Things like the probability of contention, how long locks are held, the number of threads and processors, and the amount of extra algorithmic work needed to make atomic update a viable solution. 诸如争用的可能性,持有锁的时间,线程和处理器的数量,以及使原子更新成为​​可行解决方案所需的额外算法工作量。

EDIT - in response to this question. 编辑 - 回答这个问题。

so is there a way i can measure all these probability of contention, locks held duration, etc ? 那么有没有办法可以衡量所有这些争用概率,锁定持续时间等?

In theory yes. 理论上是的。 Once you have implemented the entire application, it is possible to instrument it to measure these things. 一旦实现了整个应用程序,就可以对其进行检测以测量这些内容。 But that doesn't give you your answer either, because there isn't a predictive model you can plug these numbers into to give the answer. 但这也没有给你答案,因为没有预测模型你可以插入这些数字来给出答案。 And besides, you've already implemented the application by then. 此外,您已经实施了该应用程序。

But my point was not that measuring these factors allows you to predict performance. 但我的观点并不是衡量这些因素可以让你预测表现。 (It doesn't!) Rather, it was that a micro-benchmark does not allow you to predict performance either . (它不!)相反,它是一个微型基准不会让您无论是预测性能。

In reality, the best approach is to implement the application according to your intuition, and then use profiling as the basis for figuring out where the real performance problems are. 实际上,最好的方法是根据您的直觉实现应用程序,然后使用性能分析作为确定实际性能问题所在的基础。

These guys designed a good JVM measurement methodology so you won't fool yourself with bogus numbers, and then published it as a Python script so you can re-use their smarts - 这些人设计了一个很好的JVM测量方法,所以你不会用伪造的数字欺骗自己,然后把它作为Python脚本发布,这样你就可以重用他们的智能 -

Statistically Rigorous Java Performance Evaluation (pdf paper) 统计严谨的Java性能评估(pdf文件)

OpenJDK guys have developed a benchmarking tool called JMH: OpenJDK的人开发了一个名为JMH的基准测试工具:

http://openjdk.java.net/projects/code-tools/jmh/ http://openjdk.java.net/projects/code-tools/jmh/

This provides quite an easy to setup framework, and there is a couple of samples showing how to use that. 这提供了一个非常容易设置的框架,并且有几个示例展示了如何使用它。

http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/ http://hg.openjdk.java.net/code-tools/jmh/file/tip/jmh-samples/src/main/java/org/openjdk/jmh/samples/

Nothing can prevent you from writing the benchmark wrong, but they did a great job at eliminating the non-obvious mistakes (such as false sharing between threads, preventing dead code elimination etc). 没有什么能阻止你编写基准测试错误,但他们在消除非明显错误(例如线程之间的错误共享,防止死代码消除等)方面做得很好。

You probably want to move the loop into the task. 您可能希望将循环移动到任务中。 As it is you just start all the threads and almost immediately you're back to single threaded. 因为它只是你启动所有线程,几乎立即你回到单线程。

Usual microbenchmarking advice: Allow for some warm up. 通常的微基准测试建议:允许一些热身。 As well as average, deviation is interesting. 除了平均值,偏差也很有趣。 Use System.nanoTime instead of System.currentTimeMillis . 使用System.nanoTime而不是System.currentTimeMillis

Specific to this problem is how much the threads fight. 具体到这个问题是线程打了多少。 With a large number of contending threads, cas loops can perform wasted work. 对于大量竞争线程,cas循环可以执行浪费的工作。 Creating a SecureRandom is probably expensive, and so might System.currentTimeMillis to a lesser extent. 创建SecureRandom可能很昂贵,因此System.currentTimeMillis可能在较小程度上。 I believe SecureRandom should already be thread safe, if used correctly. 我相信如果使用正确, SecureRandom应该已经是线程安全的。

In short, you are thus searching for an "Java unit performance testing tool"? 简而言之,您正在寻找“Java单元性能测试工具”?

Use JUnitPerf . 使用JUnitPerf

Update: for the case it's not clear yet: it also supports concurrent (multithreading) testing. 更新:对于这种情况尚不清楚:它还支持并发(多线程)测试。 Here's an extract of the chapter "LoadTest" of the aforementioned link which includes a code sample: 以下是上述链接“LoadTest”一章的摘录,其中包含一个代码示例:

For example, to create a load test of 10 concurrent users with each user running the ExampleTestCase.testOneSecondResponse() method for 20 iterations, and with a 1 second delay between the addition of users, use: 例如,要创建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); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM