衡量执行时间

时间:2011-01-24 04:05:45

标签: java execution-time

我想测量生成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);
}

但结果如

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

我尝试通过将其设置为null然后调用System.gc()来处置密钥对象;但它不起作用。

任何克服此问题的建议或想法。

7 个答案:

答案 0 :(得分:4)

提高你的计数。 currentTimeMillis()分辨率功率受硬件和操作系统功能的限制。特别是,它无法实际解析为绝对精确的ms。我发现它在300毫秒范围内不准确。

如果您需要在较小的时间间隔内获得更好的精度,您可能还需要尝试System.nanoTime()。请注意,此功能的准确性将取决于操作系统。我相信我上次尝试使用Linux时会返回比Windows更准确的结果。可能或可能不是真的。

答案 1 :(得分:2)

如果generateKey()非常快,您可能希望在两次定时调用之间运行一定数量的迭代。定时器有错误(并且在获取定时器的值时会有一些开销),因此尝试计时与定时器间隔(此处为1ms)一样快或更快的事情将产生非常不准确的结果。尝试在密钥生成周围放置一个运行1000次的独立循环(但仍在外循环中)。

答案 2 :(得分:2)

微工作台标记很难。我建议您使用Google的开源项目Caliper

How do I write a correct micro-benchmark in Java?

答案 3 :(得分:1)

初始调用中的251 ms主要表示JVM正在查找“DES”算法的正确提供程序,并初始化与其关联的状态。

DES密钥只是随机的64位值(好吧,实际上是56,但这是一个不同的故事)。我希望这样做不到一毫秒。

如果你想确切地知道多少时间,可以尝试使用System.nanoTime(),它可以为纳米级分辨率提供时间(尽管它的准确度可能会略低于此值)。

答案 4 :(得分:1)

使用System.nanoTime()获取以纳秒为单位的时间。

如果您使用System.nanoTime()而不是System.currentTimeMillis(),您将获得更准确的时间。结果将如下所示:

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

答案 5 :(得分:1)

很难测量一个非常小的值 - 比如试图用尺子测量一角钱的宽度。最好在堆叠中测量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");

答案 6 :(得分:0)

这可能是因为JVM运行时优化。因此,在第一次运行时,它执行分析,并在随后的调用方法上运行得更快。

也可能是因为方法 - 第一次调用可以做一些初始化工作,比如加载类,创建对象等等。

通常,在对java代码进行基准测试时,建议先放弃几次调用。

编辑:在你的情况下,如果你不在任何地方使用那个SecretKey实例,JVM可以决定根本不需要它,并且在这个过程中甚至不会调用该代码。