简体   繁体   English

Java中的CPU执行时间

[英]CPU execution time in Java

I want to calculate how much CPU time my function takes to execute in Java.我想计算我的函数在 Java 中执行需要多少 CPU 时间。 Currently I am doing as below.目前我正在做如下。

   long startTime = System.currentTimeMillis();
    myfunction();
    long endTime = System.currentTimeMillis();
    long searchTime = endTime - startTime;

But I found out that for the same I/PI get different time depending on system load.但我发现对于相同的 I/PI,根据系统负载获得不同的时间。

So, how to get exact CPU time my function took to execute.那么,如何获得我的函数执行所需的准确 CPU 时间。

  1. System.currentTimeMillis() will only ever measure wall-clock time , never CPU time. System.currentTimeMillis()只会测量挂钟时间,永远不会测量 CPU 时间。
  2. If you need wall-clock time, then System.nanoTime() is often more precise (and never worse) than currentTimeMillis() .如果您需要挂钟时间,那么System.nanoTime()通常比currentTimeMillis()更精确(并且永远不会更糟currentTimeMillis()
  3. ThreadMXBean.getThreadCPUTime() can help you find out how much CPU time a given thread has used. ThreadMXBean.getThreadCPUTime()可以帮助您找出给定线程使用了多少 CPU 时间。 Use ManagementFactory.getThreadMXBean() to get a ThreadMXBean and Thread.getId() to find the id of the thread you're interested in. Note that this method need not be supported on every JVM!使用ManagementFactory.getThreadMXBean()获取ThreadMXBean并使用Thread.getId()查找您感兴趣的线程的id 。请注意,不需要每个 JVM 都支持此方法!

As the JVM warms up the amount of time taken will vary.随着 JVM 预热,所花费的时间会有所不同。 The second time you run this will always be faster than the first.第二次运行它总是比第一次更快。 (The first time it has to load classes and call static blocks) After you have run the method 10,000 times it will be faster again (The default threshold at which it compiles code to native machine code) (第一次必须加载类并调用静态块)在您运行该方法 10,000 次后,它将再次更快(将代码编译为本机代码的默认阈值)

To get a reproducable average timing for a micro-benchmark, I suggest you ignore the first 10,000 iterations and run it for 2-10 seconds after that.为了获得可重现的微基准平均计时,我建议您忽略前 10,000 次迭代并在此之后运行 2-10 秒。

eg例如

long start = 0;
int runs = 10000; // enough to run for 2-10 seconds.
for(int i=-10000;i<runs;i++) {
    if(i == 0) start = System.nanoTime();
    // do test
}
long time = System.nanoTime() - start;
System.out.printf("Each XXXXX took an average of %,d ns%n", time/runs);

Very important: Only do one of these loops per method.非常重要:每个方法只执行这些循环之一。 This is because it optimises the whole method based on how it is used.这是因为它根据使用方式优化了整个方法。 If you have one busy loop like this the later loops will appear slower because they have not run and will be optimised poorly.如果你有一个这样的繁忙循环,后面的循环会显得更慢,因为它们没有运行并且优化得不好。

The proper way to do Microbenchmarks is to learn about, and use correctly, the Java micobenchmark harness (JMH) , which is augmented by the JEP 230 Microbenchmark Suite from OpenJDK 12 onward.进行微基准测试的正确方法是了解并正确使用Java 微基准测试工具 (JMH) ,从 OpenJDK 12 开始, JEP 230 微基准套件对其进行了扩充。 A search for "java jmh" will yield links to some useful tutorials.搜索“java jmh”将产生一些有用教程的链接。 I liked Jakob Jenkov's blog post , and of course anything by Aleksey Shipilëv , who is the principal developer and maintainer of JMH.我喜欢Jakob Jenkov 的博客文章,当然还有Aleksey Shipilëv 的任何东西,他是 JMH 的主要开发者和维护者。 Just pick the most current version of his JMH talks on the link provided.只需在提供的链接上选择他的 JMH 演讲的最新版本。

Java benchmarking is everything but trivial, and the less work your tested code does, the deeper the rabbit hole. Java 基准测试绝非易事,您测试的代码所做的工作越少,兔子洞就越深。 Timestamping can be very misleading when trying to get a grip on performance issues.在试图解决性能问题时,时间戳可能会非常具有误导性。 The one place where timestamping does work is when you try to measure wait time for external events (such as waiting for a reply to a HTTP request and these kinds of things), as long as you can ensure that there is negligible time spent between the unblocking of a waiting thread and the taking of the "after" timestamp, and as long as the thread is unblocked duly in the first place.时间戳起作用的一个地方是当您尝试测量外部事件的等待时间(例如等待对 HTTP 请求的回复以及此类事情)时,只要您可以确保在两个事件之间花费的时间可以忽略不计等待线程的解除阻塞和“之后”时间戳的获取,只要线程首先被适当地解除阻塞。 This is typically the case if, and only if, the wait is at least in the order of tens of milliseconds.这通常是当且仅当等待时间至少为数十毫秒的情况下。 You're good if you wait seconds on something.如果你在某件事上等待几秒钟,你就很好。 Still, warmup and cache effects will occur and ruin the applicability of your measurements to real-world performance any day.尽管如此,任何一天都会发生预热和缓存效应,并破坏您的测量对实际性能的适用性。

In terms of measuring "exact CPU time", one can take the approach as detailed by Joachim Sauer's answer.在测量“确切的 CPU 时间”方面,可以采用 Joachim Sauer 的回答中详述的方法。 When using JMH, one can measure CPU usage externally and then average against the number of iterations measured, however as this will include the harness' overhead that approach is fine for comparative measurements, but not suitable to derive a "my function xy, on average, takes such-and-such number of CPU seconds on each iteration on the CPU architecture I've used.".使用 JMH 时,可以在外部测量 CPU 使用率,然后根据测量的迭代次数求平均值,但是由于这将包括线束的开销,该方法适用于比较测量,但不适合推导出“我的函数 xy,平均而言” , 在我使用过的 CPU 架构上的每次迭代中都需要花费如此多的 CPU 秒数。”。 On a modern CPU and JVM such an observation is virtually impossible to make.在现代 CPU 和 JVM 上,几乎不可能进行这样的观察。

There are a number of profilers (Jprofile, Jprobe, Yourkit) available to analyze such data.有许多分析器(Jprofile、Jprobe、Yourkit)可用于分析此类数据。 And not only this, but much more...(such as memory utilization, thread details, etc.)不仅如此,还有更多……(例如内存利用率、线程详细信息等)

you could look for your answer here:你可以在这里寻找答案:

How do I time a method's execution in Java? 如何在 Java 中为方法的执行计时?

there are many examples to calculate method's execution time有很多例子可以计算方法的执行时间

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

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