Java for循环性能问题 [英] Java for loop performance question
问题描述
考虑这个例子:
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屋!