Java for循环性能问题 [英] Java for loop performance question

查看:114
本文介绍了Java for循环性能问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑这个例子:

  public static void main(final String [] args){
final List< String> myList = Arrays.asList(A,B,C,D);
final long start = System.currentTimeMillis();
for(int i = 1000000; i> myList.size(); i--){
System.out.println(Hello);
}
last long stop = System.currentTimeMillis();
System.out.println(Finish:+(stop - start));
}

vs

  public static void main(final String [] args){
final List< String> myList = Arrays.asList(A,B,C,D);
final long start = System.currentTimeMillis();
final int size = myList.size();
for(int i = 1000000; i> size; i--){
System.out.println(Hello);
}
final long stop = System.currentTimeMillis();
System.out.println(Finish:+(stop - start));
}

这会有什么不同吗?在我的机器上,第二个似乎执行得更快,但我不知道它是否真的准确。编译器会优化这段代码吗?如果循环条件是一个不可变的对象(例如String数组),我可以认为他会的。

解决方案

这样,你必须优化你的微基准测量你关心的。



首先,使循环变得廉价,但



这里有一些代码两者:

  import java.util。*; 

public class Test {

public static long run1(){
final List< String> myList = Arrays.asList(A,B,C,D);
final long start = System.nanoTime();
int sum = 0;
for(int i = 1000000000; i> myList.size(); i--)sum + = i;
final long stop = System.nanoTime();
System.out.println(Finish:+(stop - start)* 1e-9 +ns / op; sum =+ sum);
return stop-start;
}

public static long run2(){
final List< String> myList = Arrays.asList(A,B,C,D);
final long start = System.nanoTime();
int sum = 0;
int limit = myList.size();
for(int i = 1000000000; i> limit; i--)sum + = i;
final long stop = System.nanoTime();
System.out.println(Finish:+(stop - start)* 1e-9 +ns / op; sum =+ sum);
return start-start;
}

public static void main(String [] args){
for(int i = 0; i <5; i ++){
long t1 = run1 ();
long t2 = run2();
System.out.println(Speedup =+(t1-t2)* 1e-9 +ns / op\\\
);
}
}

}

我们运行它,在我的系统我们得到:

 完成:0.481741256 ns / op; sum = -243309322 
完成:0.40228402 ns / op; sum = -243309322
Speedup = 0.079457236 ns / op

完成:0.450627151 ns / op; sum = -243309322
完成:0.43534661700000005 ns / op; sum = -243309322
Speedup = 0.015280534 ns / op

完成:0.47738474700000005 ns / op; sum = -243309322
完成:0.403698331 ns / op; sum = -243309322
Speedup = 0.073686416 ns / op

完成:0.47729349600000004 ns / op; sum = -243309322
完成:0.405540508 ns / op; sum = -243309322
Speedup = 0.071752988 ns / op

完成:0.478979617 ns / op; sum = -243309322
完成:0.36067492700000003 ns / op; sum = -243309322
Speedup = 0.11830469 ns / op

这意味着方法调用约为0.1 ns。如果你的循环执行的时间不超过1-2 ns,那么你应该关心这个。否则,不要。


considering this example:

public static void main(final String[] args) {
    final List<String> myList = Arrays.asList("A", "B", "C", "D");
    final long start = System.currentTimeMillis();
    for (int i = 1000000; i > myList.size(); i--) {
        System.out.println("Hello");
    }
    final long stop = System.currentTimeMillis();
    System.out.println("Finish: " + (stop - start));
}

vs

public static void main(final String[] args) {
    final List<String> myList = Arrays.asList("A", "B", "C", "D");
    final long start = System.currentTimeMillis();
    final int size = myList.size();
    for (int i = 1000000; i > size; i--) {
        System.out.println("Hello");
    }
    final long stop = System.currentTimeMillis();
    System.out.println("Finish: " + (stop - start));
}

Will this make any diffrence ? On my machine the second one seems to perform faster but i don't know if it is really accurate. Will the compiler optimze this code ? I could think that he would if the loop condition is an immutable object (e.g. String array).

解决方案

If you want to test something like this, you really must optimize your microbenchmark to measure what you care about.

First, make the loop inexpensive but impossible to skip. Computing a sum usually does the trick.

Second, compare the two timings.

Here's some code that does both:

import java.util.*;

public class Test {

public static long run1() {
  final List<String> myList = Arrays.asList("A", "B", "C", "D");
  final long start = System.nanoTime();
  int sum = 0;
  for (int i = 1000000000; i > myList.size(); i--) sum += i;
  final long stop = System.nanoTime();
  System.out.println("Finish: " + (stop - start)*1e-9 + " ns/op; sum = " + sum);
  return stop-start;
}

public static long run2() {
  final List<String> myList = Arrays.asList("A", "B", "C", "D");
  final long start = System.nanoTime();
  int sum = 0;
  int limit = myList.size();
  for (int i = 1000000000; i > limit; i--) sum += i;
  final long stop = System.nanoTime();
  System.out.println("Finish: " + (stop - start)*1e-9 + " ns/op; sum = " + sum);
  return stop-start;
}

public static void main(String[] args) {
  for (int i=0 ; i<5 ; i++) {
    long t1 = run1();
    long t2 = run2();
    System.out.println("  Speedup = " + (t1-t2)*1e-9 + " ns/op\n");
  }
}

}

And if we run it, on my system we get:

Finish: 0.481741256 ns/op; sum = -243309322
Finish: 0.40228402 ns/op; sum = -243309322
  Speedup = 0.079457236 ns/op

Finish: 0.450627151 ns/op; sum = -243309322
Finish: 0.43534661700000005 ns/op; sum = -243309322
  Speedup = 0.015280534 ns/op

Finish: 0.47738474700000005 ns/op; sum = -243309322
Finish: 0.403698331 ns/op; sum = -243309322
  Speedup = 0.073686416 ns/op

Finish: 0.47729349600000004 ns/op; sum = -243309322
Finish: 0.405540508 ns/op; sum = -243309322
  Speedup = 0.071752988 ns/op

Finish: 0.478979617 ns/op; sum = -243309322
Finish: 0.36067492700000003 ns/op; sum = -243309322
  Speedup = 0.11830469 ns/op

which means that the overhead of the method call is approximately 0.1 ns. If your loop does things that take no more than 1-2 ns, then you should care about this. Otherwise, don't.

这篇关于Java for循环性能问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆