简体   繁体   English

衡量执行时间

[英]Measure execution time

I want to measure the time it takes to generate DES Key, and I want to compute it several time, so that I can find the average value. 我想测量生成DES Key所需的时间,我想多次计算它,以便我可以找到平均值。

for (int x = 0; x < 10; x++)
{
     long startTime = System.currentTimeMillis();

     SecretKey key = KeyGenerator.getInstance("DES").generateKey();         

     long stopTime = System.currentTimeMillis();
     long elapsedTime = stopTime - startTime;
     System.out.println("Total Time Taken : " + elapsedTime);
}

but the result comes out like 但结果就像是

Total Time Taken : 251
Total Time Taken : 0
Total Time Taken : 0
Total Time Taken : 0
Total Time Taken : 0
Total Time Taken : 0
Total Time Taken : 0
Total Time Taken : 0
Total Time Taken : 0
Total Time Taken : 0

I tried to dispose the key object by setting it to null and then calling System.gc(); 我试图通过将其设置为null然后调用System.gc()来处置密钥对象; but it didn't work. 但它不起作用。

Any suggestion or idea to overcome this problem. 任何克服这个问题的建议或想法。

Crank up your counts. 赶上你的计数。 The currentTimeMillis() resolution power is limited by hardware and OS capabilities. currentTimeMillis()分辨率功率受硬件和操作系统功能的限制。 In particular, it isn't capable of actually resolving down to absolute exact ms. 特别是,它无法实际解析为绝对精确的ms。 I found that it isn't accurate down in the 300 ms range. 我发现它在300毫秒范围内不准确。

You may also want to try System.nanoTime() if you need better precision on small intervals. 如果您需要更小的间隔精度,您可能还想尝试System.nanoTime()。 Note that again, the accuracy of this function will depend on the operating system. 请注意,此功能的准确性将取决于操作系统。 I believe that the last time I tried this Linux would return more accurate results than Windows. 我相信我上次尝试使用Linux时会返回比Windows更准确的结果。 May or may not still be true. 可能或可能不是真的。

If generateKey() is very fast, you might want to run some number of iterations of it between the two timing calls. 如果generateKey()非常快,您可能希望在两个定时调用之间运行一定数量的迭代。 Timers have error (and there is some overhead in getting the timer's value), and so trying to time things that are as fast or faster than the timer interval (1ms here) will produce very inaccurate results. 定时器有错误(并且在获取定时器的值时会有一些开销),因此尝试计时与定时器间隔(此处为1ms)一样快或更快的事情将产生非常不准确的结果。 Try putting a separate loop that runs 1000 times around just the key generation (but still within your outer loop). 尝试在密钥生成周围放置一个运行1000次的独立循环(但仍然在外部循环中)。

Micro bench marking is hard. 微型台架标记很难。 I suggest you use Google's open source project Caliper for this. 我建议您使用Google的开源项目Caliper

How do I write a correct micro-benchmark in Java? 如何在Java中编写正确的微基准测试?

The 251 ms in the initial call primarily represents the JVM's looking up the correct provider for the "DES" algorithm, and initializing the state associated with it. 初始调用中的251 ms主要表示JVM正在查找“DES”算法的正确提供程序,并初始化与其关联的状态。

DES keys are just random 64-bit values (well, actually 56, but that's a different story). DES密钥只是随机的64位值(好吧,实际上是56,但这是一个不同的故事)。 I'd expect that it takes less than a millisecond to do that. 我希望这样做不到一毫秒。

If you want to see exactly how much time, try using System.nanoTime(), which gives time at a nanosecond resolution (though its accuracy might be somewhat less than that) for exactly this type of application. 如果你想确切地知道多少时间,可以尝试使用System.nanoTime(),它为这种类型的应用程序提供了一个纳秒分辨率的时间(虽然它的准确度可能略低于那个)。

Use System.nanoTime() to get the time in nanoseconds. 使用System.nanoTime()以纳秒为单位获取时间。

You'll get more accurate times if you use System.nanoTime() rather than System.currentTimeMillis() . 如果使用System.nanoTime()而不是System.currentTimeMillis()您将获得更准确的时间。 Results will look like this: 结果将如下所示:

Total Time Taken : 687562592
Total Time Taken : 51328
Total Time Taken : 33838
Total Time Taken : 25474
Total Time Taken : 22432
Total Time Taken : 29656
Total Time Taken : 23192
Total Time Taken : 28516
Total Time Taken : 22812
Total Time Taken : 21672

It can be hard to measure a really small value - like trying to measure the width of a dime with a ruler. 很难测量一个非常小的值 - 比如试图用尺子测量一角钱的宽度。 You're better off measuring 10 or 20 of them in a stack and then dividing the measurement by the number of them in the stack. 最好在堆栈中测量10或20个,然后将测量值除以堆栈中的数量。

int iterations = 1000;

long startTime = System.currentTimeMillis();
for (int x = 0; x < iterations; x++) {
     SecretKey key = KeyGenerator.getInstance("DES").generateKey();         
}
long stopTime = System.currentTimeMillis();

long elapsedTime = stopTime - startTime;
double average = elapsedTime/((double) iterations);
System.out.println("Total Time Taken : " + average + " ms");

It can be because of JVM run-time optimisations. 这可能是因为JVM运行时优化。 So on the first runs it performs profiling, and on subsequent invocations method runs much quicker. 因此,在第一次运行时,它执行分析,并在随后的调用方法上运行得更快。

Also it can be the because of the method - the first invocation can do some initialization work, like loading classes, creating objects and so on. 也可以是因为方法 - 第一次调用可以做一些初始化工作,比如加载类,创建对象等等。

Usually, when doing benchmarking of java code it is recommended to discard first several invocations. 通常,在对java代码进行基准测试时,建议先放弃几次调用。

EDIT: And in your case, if you don't use that SecretKey instance anywhere, JVM can decide that it is not needed at all, and that code is not even called in the process. 编辑:在您的情况下,如果您不在任何地方使用该SecretKey实例,JVM可以决定根本不需要它,并且在该过程中甚至不会调用该代码。

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

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