2

我想测量生成 DES 密钥所需的时间,我想计算几次,以便找到平均值。

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(); 来处理它。但它没有用。

任何解决此问题的建议或想法。

4

7 回答 7

4

增加你的计数。currentTimeMillis() 解析能力受硬件和操作系统能力的限制。特别是,它实际上无法解析到绝对精确的毫秒。我发现它在 300 毫秒范围内并不准确。

如果您需要在小间隔上获得更好的精度,您可能还想尝试 System.nanoTime()。请再次注意,此函数的准确性将取决于操作系统。我相信我上次尝试这个 Linux 时会返回比 Windows 更准确的结果。可能仍然是真实的,也可能不是真实的。

于 2011-01-24T04:12:53.733 回答
2

如果generateKey()速度非常快,您可能希望在两次计时调用之间运行一些迭代次数。计时器有错误(并且在获取计时器的值方面存在一些开销),因此尝试对与计时器间隔(此处为 1 毫秒)一样快或更快的事情进行计时将产生非常不准确的结果。尝试放置一个单独的循环,该循环仅围绕密钥生成运行 1000 次(但仍在您的外部循环内)。

于 2011-01-24T04:12:58.987 回答
2

微基准标记很难。我建议您为此使用 Google 的开源项目Caliper

如何在 Java 中编写正确的微基准测试?

于 2011-01-24T04:13:16.810 回答
1

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

DES 密钥只是随机的 64 位值(嗯,实际上是 56,但那是另一回事)。我希望这样做只需不到一毫秒。

如果您想确切了解多少时间,请尝试使用 System.nanoTime(),它为这种类型的应用程序提供纳秒分辨率的时间(尽管其精度可能略低于该精度)。

于 2011-01-24T04:18:51.827 回答
1

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

如果您使用System.nanoTime()而不是System.currentTimeMillis(). 结果将如下所示:

总时间:687562592
总时间:51328
总时间:33838
总时间:25474
总时间:22432
总时间:29656
总时间:23192
总时间:28516
总时间:22812
总时间:21672
于 2011-01-24T04:23:54.040 回答
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");
于 2011-01-24T04:32:57.900 回答
0

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

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

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

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

于 2011-01-24T04:09:48.060 回答