简体   繁体   English

Java System.currentTimeMillis() 方法的正确用法?

[英]Correct usage of Java System.currentTimeMillis() method?

I am comparing the time to compute both iterative and recursive factorial procedures in Java. I am trying to use the System.currentTimeMillis method to compare the time it takes for each algorithm to compute, but I can't seem to calculate the difference.我正在比较 Java 中计算迭代和递归阶乘过程的时间。我正在尝试使用System.currentTimeMillis方法来比较每种算法计算所需的时间,但我似乎无法计算差异。 I am not sure what the proper way to use this method is, but any event here is what I am trying to achieve in my code:我不确定使用此方法的正确方法是什么,但这里的任何事件都是我试图在我的代码中实现的:

// ... more code above

System.out.print("Please enter an integer: ");
int integer = readInt();
System.out.println();

// demonstrate recursive factorial and calculate
// how long it took to complete the algorithm
long time1 = System.currentTimeMillis();
int fact1 = factRecursive(integer);
long time2 = System.currentTimeMillis();
System.out.format("Result of recursive factorial %s is %d\n", integer, fact1);
System.out.format("Algorithm took %d milliseconds\n\n", (time2 - time1));

// ... more code below

Here is the output:这是 output:

Please enter an integer: 25

Result of recursive factorial 25 is 2076180480
Algorithm took 0 milliseconds

Result of iterative factorial 25 is 2076180480
Algorithm took 0 milliseconds

Clearly I must be doing something wrong here, as the amount of time expected to compute factorials for both cases shouldn't be zero.显然,我一定是在这里做错了什么,因为两种情况下计算阶乘的预期时间不应该为零。

EDIT: Here are my solutions for factorial, if anyone is interested (not particularly unique, but here they are anyway):编辑:这是我的阶乘解决方案,如果有人感兴趣的话(不是特别独特,但无论如何它们都在这里):

// factRecursive uses a recursive algorithm for 
// caluclating factorials.
public static long factRecursive(long n)
{
    return n = (n == 1)? 1 : n * factRecursive(n - 1);
}

// factIterative uses an iterative algorithm for
// calculating factorials.
public static long factIterative(long n)
{
    long product = 1;

    if(n == 1) return n;

    for(int i = 1; i <= n; ++i)
        product *= i;

    return product;
}

And is some output. Surprisingly, the recursive version holds up well.并且是一些 output。令人惊讶的是,递归版本运行良好。 It isn't until about 39. that the iterative version starts performing noticeably better.直到 39 岁左右,迭代版本才开始明显好转。

Please enter an integer: 39

Result of recursive factorial 39 is 2304077777655037952
Algorithm took 5828 nanoseconds

Result of iterative factorial 39 is 2304077777655037952
Algorithm took 5504 nanoseconds

The resolution of System.currentTimeMillis() can vary, depending on your system; System.currentTimeMillis()的分辨率可能会有所不同,具体取决于您的系统; it appears that your algorithm is too fast to measure with this timer.看来您的算法太快了,无法使用此计时器进行测量。

Use System.nanoTime() instead.请改用System.nanoTime() Its accuracy is also system dependent, but at least it is capable of high resolution time measurement.它的准确性也取决于系统,但至少它能够进行高分辨率时间测量。

Just-in-time compilation can have a big impact on performance, but most virtual machines require a method to be invoked many times before recompiling it.即时编译会对性能产生很大影响,但大多数虚拟机都需要在重新编译之前多次调用某个方法。 This makes it difficult to get accurate results from this kind of micro-benchmark.这使得很难从这种微基准测试中获得准确的结果。

A well-written factorial function should execute very quickly for n = 25, so having it run in approximately 0ms isn't terribly surprising.对于 n = 25,一个写得很好的阶乘 function 应该执行得非常快,所以让它在大约 0 毫秒内运行并不奇怪。 You have three options:您有以下三种选择:

  1. Use a larger n.使用更大的 n。 This will cause the factorial function to take longer, and give you something to measure.这将导致阶乘 function 花费更长的时间,并给你一些东西来衡量。
  2. Measure time in approximate nanoseconds rather than milliseconds, using System.nanoTime .使用System.nanoTime以近似纳秒而不是毫秒来测量时间。
  3. I recommend doing both 1 and 2.我建议同时执行 1 和 2。

As other answerers have pointed out, you are indeed subtracting end from start, which is backwards.正如其他回答者指出的那样,您确实是从开始减去结束,这是倒退的。 Obviously, you should fix that too.显然,你也应该解决这个问题。 But that change only affects the sign of the result, not the absolute value.但这种变化只会影响结果的符号,不会影响绝对值。


EDIT : Just to see how fast it is to find the factorial of 25, I wrote this Python implementation编辑:只是为了看看找到 25 的阶乘有多快,我写了这个 Python 实现

>>> def fact(n):
...     def _fact(n, acc):
...             if n == 1:
...                     return acc
...             return _fact(n - 1, n * acc)
...     if n < 0:
...             return 0 # Or raise an exception
...     if n < 2:
...             return 1
...     return _fact(n, 1)
... 
>>> fact(25)
15511210043330985984000000L
>>> import timeit
>>> t = timeit.Timer("fact(25)", "from __main__ import fact")
>>> print t.timeit()
6.2074379921

Even though Python is an interpreted dynamically typed language without tail call optimization, a simple recursive solution with an accumulator can find fact(25) a million times in 6.2 seconds on my machine.尽管 Python 是一种没有尾调用优化的解释型动态类型语言,但使用累加器的简单递归解决方案可以在我的机器上在 6.2 秒内找到一百万次fact(25) So the average execution time is 6.2 microseconds.所以平均执行时间是 6.2 微秒。 Not a chance of measuring a substantial difference between an iterative and recursive solution on a single run with millisecond clock precision.没有机会在具有毫秒时钟精度的单次运行中测量迭代和递归解决方案之间的实质性差异。

You need to do (finish time - start time), you have it backward.你需要做的(完成时间 - 开始时间),你已经落后了。

try this:试试这个:

System.out.format("Algorithm took %d milliseconds\n\n", (time2 - time1));

very usual mistake.很常见的错误。 You should be subtracting time1 from time2.您应该从 time2 中减去 time1。

It will help if you name your variables sensibly - for example startTime and endTime so you would know or at least spot that you have to do endTime - startTime as endTime > startTime如果您明智地命名您的变量将会有所帮助 - 例如startTimeendTime这样您就会知道或至少发现您必须做endTime - startTime as endTime > startTime

Looks like your fast recursive may not be doing such a heavy processing after all.看起来您的快速递归毕竟可能不会进行如此繁重的处理。

Please use System.nanoTime() instead.请改用System.nanoTime() It returns nano seconds它返回纳秒

http://docs.oracle.com/javase/7/docs/api/java/lang/System.html http://docs.oracle.com/javase/7/docs/api/java/lang/System.html

nanoTime() Returns the current value of the running Java Virtual Machine's high-resolution time source, in nanoseconds. nanoTime() 返回正在运行的 Java 虚拟机的高分辨率时间源的当前值,以纳秒为单位。


Another way to test is by iterating your factorial say a 1000 times.另一种测试方法是将阶乘迭代 1000 次。 then divide the time difference by 1000.00 (double)然后将时差除以 1000.00(双倍)

To get a meaningful timed result you need to repeat it, and ignore, at least the first 10,000 times you call a method (so the code is compiled) and you need to run it for a further 2-10 seconds (repeatedly).要获得有意义的计时结果,您需要重复并忽略调用方法的前 10,000 次(因此代码已编译),并且您需要再运行 2-10 秒(重复)。

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

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