Java 倒计时还是倒计时,哪个更快?

Java 倒计时还是倒计时,哪个更快?,java,performance,loops,Java,Performance,Loops,可能重复: 如果我写一个循环作为 for (int i=n; i>=0; i--) 另一个是 for (int i=0; i<=n; i++) for(int i=0;i只需以最有意义的方式编写循环即可。您不太可能(a)在整个程序过程中多做几纳秒会产生影响的时间关键性操作,以及(b)您的代码经过优化,瓶颈是循环中的递增或递减操作 如果在测试之后,评测显示某个特定循环存在问题,那么就要考虑优化该循环,将重点放在循环体上,而不是像递增和递减这样的事情。CPU可能有一种更快的方法来比

可能重复:

如果我写一个循环作为

for (int i=n; i>=0; i--)
另一个是

for (int i=0; i<=n; i++)

for(int i=0;i只需以最有意义的方式编写循环即可。您不太可能(a)在整个程序过程中多做几纳秒会产生影响的时间关键性操作,以及(b)您的代码经过优化,瓶颈是循环中的递增或递减操作


如果在测试之后,评测显示某个特定循环存在问题,那么就要考虑优化该循环,将重点放在循环体上,而不是像递增和递减这样的事情。

CPU可能有一种更快的方法来比较数字(i)和0,而不是比较另一个任意数字(n).这在理论上会使减量版本更快


但这纯粹是学术性的,伊姆霍。他们基本上是“一样的”,因此您应该实现一个更符合逻辑且更易于理解的方法,无论是谁在您之后维护您的代码。

不足为奇;请使用谷歌卡尺来找出答案。因为已经有相当多的讨论围绕着测试的相对权重(零与上限、递增与递减),这里是笛卡尔乘积在所有这些情况中:

import java.util.Random;

import com.google.caliper.Runner;
import com.google.caliper.SimpleBenchmark;

public class Performance extends SimpleBenchmark {
  static final Random rnd = new Random();

  public int timeDecrementToZero(int reps) {
    int sum = rnd.nextInt();
    for (int i = 0; i < reps; i++) {
      for (int j = Integer.MAX_VALUE; j >= 0; j--) sum += j;
    }
    return sum;
  }
  public int timeDecrementFromZero(int reps) {
    int sum = rnd.nextInt();
    for (int i = 0; i < reps; i++) {
      for (int j = 0; j > Integer.MIN_VALUE; j--) sum += j;
    }
    return sum;
  }
  public int timeIncrementFromZero(int reps) {
    int sum = rnd.nextInt();
    for (int i = 0; i < reps; i++) {
      for (int j = 0; j < Integer.MAX_VALUE; j++) sum += j;
    }
    return sum;
  }
  public int timeIncrementToZero(int reps) {
    int sum = rnd.nextInt();
    for (int i = 0; i < reps; i++) {
      for (int j = Integer.MIN_VALUE; j < 0; j++) sum += j;
    }
    return sum;
  }

  public static void main(String... args) {
    Runner.main(Performance.class, args);
  }
}
显然,无论限制是否为零,其效果都不如使用inc和dec

让我们稍微改变一下。。。 为了指出这些差异有多严重,这里的代码实际上是相同的,但现在它使用了
long
s(我包括第一个示例中的一种方法,用于保持规模):


主要结论:永远不要在如此低的级别上对性能做任何假设。编写完整的代码并作为一个整体进行测试,因为总会有一些你没有考虑到的东西,这完全改变了局面。

如果有任何可测量的差异,那么与0相比的变体会更快,因为在CPU级别上与0的比较速度更快。
但是,在大多数情况下,您最好使用可读性好的代码。在大多数情况下,与其他人了解所发生的事情所需的时间相比,时间上的差异是微不足道的。只需使用最简单的方法即可。如果您想测试它,您可以运行以下操作:

long startTime = System.nanoTime();  
long duration, endTime;  

for (int i=0;i<1000 ;i++ ) {  
        //function
   }  

endTime = System.nanoTime();  
duration = endTime - startTime;  

System.out.printf("The duration was %d.%03d microseconds%n", duration / 1000, duration % 1000); 
long startTime=System.nanoTime();
持续时间长,结束时间长;

对于(int i=0;i答案是它取决于
n
是什么。当倒计时时,代码只需要访问
n
一次。当倒计时时,这可能不是真的。因此,例如,如果
n
是一个
易失性
字段,或者如果循环体中的某些内容可能会更改
n
的值,则该值需要为loo每次通过循环都会加速。这将显著降低循环速度

使用此代码,向上计数比向下计数慢几百倍:

public class Counts {
    private static final int ITERS = 100000;
    volatile int n = 1000;

    public long countUp() {
        long start = System.nanoTime();
        for (int iter = 0; iter < ITERS; ++iter) {
            for (int i = 0; i < n; ++i) {
                // do nothing
            }
        }
        return System.nanoTime() - start;
    }

    public long countDown() {
        long start = System.nanoTime();
        for (int iter = 0; iter < ITERS; ++iter) {
            for (int i = n - 1; i >= 0; --i) {
                // do nothing
            }
        }
        return System.nanoTime() - start;
    }
}
公共类计数{
专用静态最终积分=100000;
挥发性int n=1000;
公众长时间倒数{
长启动=System.nanoTime();
用于(国际热核试验堆=0;国际热核试验堆<国际热核试验堆;++国际热核试验堆){
对于(int i=0;i=0;--i){
//无所事事
}
}
返回系统.nanoTime()-开始;
}
}

自己运行它并计时。我记得看到过减量比增量慢的情况,尽管时间很短。10毫秒左右。就性能而言,它们都是相同的,
++
-
的性能不同,但没有实际的区别。即使有,你也需要延长e循环,以便以可能损害应用程序整体性能的方式实际注意到它。@Max“10毫秒左右”是什么意思?我们这里说的是纳秒。这不是inc或dec的问题,更像是与0或nMan相比的问题,这太棒了。但为什么我不能下载它?这是下载的正确链接吗-?没有可下载的工件,请查看源代码。我不相信这是一个重要的结果。在它中引入求和我怀疑,e方向可能对所用时间有更大的影响,而且由于您迭代到INTEGER.MAX_值,并求和为int,您也会遇到整数溢出。问题不是减量与增量,而是与零的比较。这是没有意义的。请尝试将
n
设为易失性字段(或者在循环中执行某些操作,使编译器无法识别
n
在循环的持续时间内是恒定的),那么您的结果将完全不同。
 0% Scenario{vm=java, trial=0, benchmark=DecrementFromZeroInt} 978513000.00 ns; σ=14861284.82 ns @ 10 trials
20% Scenario{vm=java, trial=0, benchmark=DecrementFromZero} 2160652000.00 ns; σ=13825686.87 ns @ 3 trials
40% Scenario{vm=java, trial=0, benchmark=IncrementFromZero} 2153370000.00 ns; σ=6318160.49 ns @ 3 trials
60% Scenario{vm=java, trial=0, benchmark=DecrementToZero} 4379893000.00 ns; σ=8739917.79 ns @ 3 trials
80% Scenario{vm=java, trial=0, benchmark=IncrementToZero} 4383569000.00 ns; σ=5798095.89 ns @ 3 trials

           benchmark   ms linear runtime
DecrementFromZeroInt  979 ======
   DecrementFromZero 2161 ==============
   IncrementFromZero 2153 ==============
     DecrementToZero 4380 =============================
     IncrementToZero 4384 ==============================
long startTime = System.nanoTime();  
long duration, endTime;  

for (int i=0;i<1000 ;i++ ) {  
        //function
   }  

endTime = System.nanoTime();  
duration = endTime - startTime;  

System.out.printf("The duration was %d.%03d microseconds%n", duration / 1000, duration % 1000); 
public class Counts {
    private static final int ITERS = 100000;
    volatile int n = 1000;

    public long countUp() {
        long start = System.nanoTime();
        for (int iter = 0; iter < ITERS; ++iter) {
            for (int i = 0; i < n; ++i) {
                // do nothing
            }
        }
        return System.nanoTime() - start;
    }

    public long countDown() {
        long start = System.nanoTime();
        for (int iter = 0; iter < ITERS; ++iter) {
            for (int i = n - 1; i >= 0; --i) {
                // do nothing
            }
        }
        return System.nanoTime() - start;
    }
}