performance - Simple string concat example fast in Java 7, slow in Java 8 -
i have little class demonstrates timing characteristics of different ways concatenate strings (stringbuilder vs. plain string contatenation). irrespective of relative timings of each strategy, noticed particular performance behavior java 6, , later java 7, , java 8.
i had first written java 6, , impressed large improvements saw java 7. had assumed java 8 show similar performance. however, when run on win7/64-bit laptop, find java 8 numbers slower java 6 numbers.
it's entirely possible i'm seeing issues java 6 , 7 jvm removing code i'm testing @ runtime (a common obstacle microbenchmarks), don't know.
i'm going show perf numbers 3 runs, , i'll include source code. note test has hefty warmup pass, should result in classloading , jit work finishing before timing runs.
also note relative timings in java 6 , java 8 "consistent". instance, expect tests 2 , 3 2 fastest, 2 faster 3, or vice versa. java 7 timings lower that, , same, it's possible have issue java 7 jit cutting out code.
java 6: stringbuilder0:499 stringbuilder1:260 stringbuilder2:262 stringbuilder3:180 stringbuilder4:184 stringbuilder5:210 stringbuilder6:286 stringbuilder7:287 stringbuilder8:203 stringbuilder9:248 java 7: stringbuilder0:66 stringbuilder1:269 stringbuilder2:57 stringbuilder3:57 stringbuilder4:57 stringbuilder5:57 stringbuilder6:299 stringbuilder7:57 stringbuilder8:57 stringbuilder9:57 java 8: stringbuilder0:714 stringbuilder1:367 stringbuilder2:368 stringbuilder3:279 stringbuilder4:271 stringbuilder5:318 stringbuilder6:415 stringbuilder7:406 stringbuilder8:308 stringbuilder9:349 here 2 classes generate data.
stringbuildertests:
package timings; public class stringbuildertests { public static void main(string[] args) { stringbuildertests stringbuildertests = new stringbuildertests(args); stringbuildertests.go(); } public stringbuildertests(string[] args) { } private void go() { final string str1 = "01234567890123456789012345678901234567890123456789012345678901234567890123456789"; final string str2 = "abcdefghiabcdefghiabcdefghiabcdefghiabcdefghi"; final string str3 = "xxxxxxxxxxxxxxxx"; final string str4 = "yyyyyyyyyyyyyyyy"; final string str5 = "zzzzzzzzzzzzzzzz"; system.out.println("running warmup pass."); (int ctr = 0; ctr < 20000; ++ ctr) { teststringbuilder0(str1, str2, str3, str4, str5); teststringbuilder1(str1, str2, str3, str4, str5); teststringbuilder2(str1, str2, str3, str4, str5); teststringbuilder3(str1, str2, str3, str4, str5); teststringbuilder4(str1, str2, str3, str4, str5); teststringbuilder5(str1, str2, str3, str4, str5); teststringbuilder6(str1, str2, str3, str4, str5); teststringbuilder7(str1, str2, str3, str4, str5); teststringbuilder8(str1, str2, str3, str4, str5); teststringbuilder9(str1, str2, str3, str4, str5); } int iters = 10000000; system.out.println("starting timing runs."); new timingcontainer(iters, "stringbuilder0", new timingtest() { public void run() { teststringbuilder0(str1, str2, str3, str4, str5); } }).run(); new timingcontainer(iters, "stringbuilder1", new timingtest() { public void run() { teststringbuilder1(str1, str2, str3, str4, str5); } }).run(); new timingcontainer(iters, "stringbuilder2", new timingtest() { public void run() { teststringbuilder2(str1, str2, str3, str4, str5); } }).run(); new timingcontainer(iters, "stringbuilder3", new timingtest() { public void run() { teststringbuilder3(str1, str2, str3, str4, str5); } }).run(); new timingcontainer(iters, "stringbuilder4", new timingtest() { public void run() { teststringbuilder4(str1, str2, str3, str4, str5); } }).run(); new timingcontainer(iters, "stringbuilder5", new timingtest() { public void run() { teststringbuilder5(str1, str2, str3, str4, str5); } }).run(); new timingcontainer(iters, "stringbuilder6", new timingtest() { public void run() { teststringbuilder6(str1, str2, str3, str4, str5); } }).run(); new timingcontainer(iters, "stringbuilder7", new timingtest() { public void run() { teststringbuilder7(str1, str2, str3, str4, str5); } }).run(); new timingcontainer(iters, "stringbuilder8", new timingtest() { public void run() { teststringbuilder8(str1, str2, str3, str4, str5); } }).run(); new timingcontainer(iters, "stringbuilder9", new timingtest() { public void run() { teststringbuilder9(str1, str2, str3, str4, str5); } }).run(); } private void useit(string str) { system.out.print(str.charat(0)); } public static string teststringbuilder0(string str1, string str2, string str3, string str4, string str5) { string result = null; result = result + str1; result = result + str2; result = result + str3; result = result + str4; result = result + str5; return result; } public static string teststringbuilder1(string str1, string str2, string str3, string str4, string str5) { stringbuilder sb = new stringbuilder(); sb.append(str1); sb.append("-"); sb.append(str2); sb.append("-"); sb.append(str3); sb.append("-"); sb.append(str4); sb.append("-"); sb.append(str5); return sb.tostring(); } public static string teststringbuilder2(string str1, string str2, string str3, string str4, string str5) { return new stringbuilder(). append(str1).append("-").append(str2).append("-").append(str3).append("-").append(str4).append("-").append(str5). tostring(); } public static string teststringbuilder3(string str1, string str2, string str3, string str4, string str5) { return new stringbuilder(str1).append("-").append(str2).append("-").append(str3).append("-").append(str4).append("-").append(str5).tostring(); } public static string teststringbuilder4(string str1, string str2, string str3, string str4, string str5) { return str1 + "-" + str2 + "-" + str3 + "-" + str4 + "-" + str5; } public static string teststringbuilder5(string str1, string str2, string str3, string str4, string str5) { return new stringbuilder(160). append(str1).append("-").append(str2).append("-").append(str3).append("-").append(str4).append("-").append(str5). tostring(); } public static string teststringbuilder6(string str1, string str2, string str3, string str4, string str5) { stringbuffer sb = new stringbuffer(); sb.append(str1); sb.append("-"); sb.append(str2); sb.append("-"); sb.append(str3); sb.append("-"); sb.append(str4); sb.append("-"); sb.append(str5); return sb.tostring(); } public static string teststringbuilder7(string str1, string str2, string str3, string str4, string str5) { return new stringbuffer(). append(str1).append("-").append(str2).append("-").append(str3).append("-").append(str4).append("-").append(str5). tostring(); } public static string teststringbuilder8(string str1, string str2, string str3, string str4, string str5) { return new stringbuffer(str1).append("-").append(str2).append("-").append(str3).append("-").append(str4).append("-").append(str5).tostring(); } public static string teststringbuilder9(string str1, string str2, string str3, string str4, string str5) { return new stringbuffer(160). append(str1).append("-").append(str2).append("-").append(str3).append("-").append(str4).append("-").append(str5). tostring(); } } timingcontainer:
package timings; public class timingcontainer { private int iterations; private string label; private timingtest timingtest; public timingcontainer(int iterations, string label, timingtest timingtest) { this.iterations = iterations; this.label = label; this.timingtest = timingtest; } public void run() { long starttime = system.nanotime(); (int ctr = 0; ctr < iterations; ++ ctr) { timingtest.randomize(); timingtest.run(); } long endtime = system.nanotime(); long totalns = (endtime - starttime); system.out.println(label + ":" + (totalns / iterations)); } } update:
timingtest:
package timings; public abstract class timingtest { public abstract void run(); public void randomize() {} }
the discrepancy was comparing 64-bit java 7 32-bit java 8 (the eclipse in spring tool suite 3.5.0 apparently won't work 64-bit java 8, why had 32-bit java 8 distro).
once ran test 64-bit java 8, got more reasonable results.
in addition, learned jmh, handy writing , running microbenchmarks need accurate.
Comments
Post a Comment