Local member is faster or instance member

The following code proves that method1 is faster than method2. Someone can comment on the reason for this behavior.

class Trial { String _member; void method1() { for(int i=0;i<30480;i++) { _member += "test"; } } void method2() { String temp=""; for(int i=0;i<30480;i++) { temp += "test"; } _member = temp; } public static void main(String args[]) { Trial t = new Trial(); long startTime1 = System.currentTimeMillis(); t.method1(); long endTime1 = System.currentTimeMillis(); long startTime2 = System.currentTimeMillis(); t.method2(); long endTime2 = System.currentTimeMillis(); System.out.println(endTime1 - startTime1); System.out.println(endTime2 - startTime2); } } 
+6
source share
3 answers

The following code proves that method1 is faster than method2

No. This is not to prove .

It depends on many factors. When I run this code, I get

 1403 1248 

So, in my environment, your code "proves" that method1 is slower than method2.

When benchmarking, you need to take care of effects such as caching and JVM warm-ups.

see also

for more information.


I reorganized the main method a bit:

 ... static void doBenchmark() { Trial t = new Trial(); long startTime1 = System.currentTimeMillis(); t.method1(); long endTime1 = System.currentTimeMillis(); long startTime2 = System.currentTimeMillis(); t.method2(); long endTime2 = System.currentTimeMillis(); System.out.println(endTime1 - startTime1); System.out.println(endTime2 - startTime2); } public static void main(String args[]) { for (int i = 0; i < 20; i++) { doBenchmark(); System.out.println("----"); } } 

This leads to similar values โ€‹โ€‹for the first iteration of for -loop, but then the results converge and will not differ significantly:

 1396 1133 ---- 1052 1070 ---- 688 711 ---- 728 726 ---- 715 709 ---- ... 

Even sometimes method1 seems faster, and sometimes method2 - this is most likely due to inaccuracy of the measurement.

+12
source

After warming up jvm several times, you will see that method2 is faster than method1 .

Here is my re-factored code:

 class Trial { String _member; void method1() { for (int i = 0; i < 30480; i++) { _member += "test"; } } void method2() { String temp = ""; for (int i = 0; i < 30480; i++) { temp += "test"; } _member = temp; } public static void main(String args[]) { Trial t = new Trial(); for (int i = 0; i < 10; i++) { //warm up jvm t.method1(); t.method2(); } t = new Trial(); long startTime1 = System.currentTimeMillis(); t.method1(); long endTime1 = System.currentTimeMillis(); long startTime2 = System.currentTimeMillis(); t.method2(); long endTime2 = System.currentTimeMillis(); System.out.println(endTime1 - startTime1); System.out.println(endTime2 - startTime2); } } 

And here is the result:

 ---- 2910 2894 ---- 

But for actual benchmarking you have to run it several times and observe the statistical behavior, and only then can you make any conclusion!

0
source

I changed the number of tests, but not the method, here with StringBuilder 2500 3000 times faster!

 class Trial { StringBuilder _member = new StringBuilder(243840); void method1() { for (int i = 0; i < 30480; i++) { _member.append("test"); } } void method2() { final StringBuilder temp = new StringBuilder(243840); for (int i = 0; i < 30480; i++) { temp.append("test"); } _member = temp; } public static void main(final String args[]) { long startTime1 = System.nanoTime(); new Trial().method1(); long endTime1 = System.nanoTime(); long startTime2 = System.nanoTime(); new Trial().method2(); long endTime2 = System.nanoTime(); System.out.println(endTime1 - startTime1); System.out.println(endTime2 - startTime2); System.out.println("------------------"); startTime1 = System.nanoTime(); new Trial().method1(); endTime1 = System.nanoTime(); startTime2 = System.nanoTime(); new Trial().method2(); endTime2 = System.nanoTime(); System.out.println(endTime1 - startTime1); System.out.println(endTime2 - startTime2); } } 

Output:

 method1 then method2 with += in MILLIisecond 5563 5844 ............................................ 5437 6344 method2 then method1 with += in MILLIisecond 4625 5969 ------------------ 6531 4891 ===================================================== method1 then method2 with StringBuilder in NANOsecond 3530337 2074286 ------------------ 2058641 1983493 ..................................................... method2 then method1 with StringBuilder in NANOsecond 3430883 1698819 ------------------ 2065626 2144406 

So, since @Andreas said this is not a good way to test performance.

Highlight: use a declared size StringBuilder (in Joshua Bloch's book Effective Java article 51: Beware of string concatenation performance)
- prefer method2 () when possible: The [Builder] line is inside it and does not use external

0
source

Source: https://habr.com/ru/post/947525/


All Articles