рдЗрд╕рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░рдХреЗ рдкреНрд░рджрд░реНрд╢рди рдХреЛ рдХреИрд╕реЗ рдиреАрдЪрд╛ рджрд┐рдЦрд╛рдпрд╛ рдЬрд╛рдП

рд╣рдо рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рдЪрд╛рд╣рддреЗ рдереЗ, рд▓реЗрдХрд┐рди рдпрд╣ рд╣рдореЗрд╢рд╛ рдХреА рддрд░рд╣ рдирд┐рдХрд▓рд╛ред
рд╡рд┐рдХреНрдЯрд░ рдЪреЗрд░реНрдиреЛрдорд┐рд░рд┐рди,
рд░реВрд╕реА рд░рд╛рдЬрдиреЗрддрд╛


рдЬрд╝рд┐рдиреНрджрдЧреА рдореЗрдВ рдХрдИ рдмрд╛рд░ рдРрд╕рд╛ рд╣реЛрддрд╛ рд╣реИ рдЬрдм рдЖрдк рд╕рдм рдХреБрдЫ рд╕рд╣реА рдХрд░рддреЗ рдирдЬрд╝рд░ рдЖрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдХреБрдЫ рдЧрд▓рдд рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред
рдпрд╣ рдХрд╣рд╛рдиреА рдРрд╕реЗ рд╣реА рдПрдХ рдорд╛рдорд▓реЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣реИред


рдПрдХ рдмрд╛рд░ рдореИрдВрдиреЗ рдЗрд╕ рдХреЛрдб рдХреЛ рджреЗрдЦрд╛ рдФрд░ рдЗрд╕реЗ рдЧрддрд┐ рджреЗрдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪрд╛:


public String appendBounds(Data data) { int beginIndex = data.beginIndex; int endIndex = data.endIndex; return new StringBuilder() .append('L') .append(data.str, beginIndex, endIndex) .append(';') .toString(); } 

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдореИрдВ рдЪрд░ рдХреА рдХреБрд▓ рд▓рдВрдмрд╛рдИ рдХреА рдЧрдгрдирд╛ рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдЪрд░ beginIndex рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ beginIndex рдФрд░ endIndex (рд╕рд╛рде рд╣реА рдЗрд╕ рддрдереНрдп рдХреЗ рд╕рд╛рде рдХрд┐ рдЫрдВрдЯрдиреА рдХреА рдЧрдИ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╕реНрдЯреНрд░реАрдВрдЧрдмреБрдЗрдЯ рдореЗрдВ 2 рдФрд░ рдкрд╛рддреНрд░реЛрдВ рдХреЛ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдПрдЧрд╛), рдФрд░ рдЖрд╡рд╢реНрдпрдХ рдорд╛рди рдХреЗ рдЖрдХрд╛рд░ рдХрд╛ рдЪрдпрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕ рдореВрд▓реНрдп рдХреЛ рддреБрд░рдВрдд рд╕реНрдЯреНрд░рд┐рдВрдЧ рдирд┐рд░реНрдорд╛рддрд╛ рдХреЗ рдкрд╛рд╕ рджреЗрдВред ред рдпрд╣ рд╡рд┐рдЪрд╛рд░ рдореБрдЭреЗ рдмрд╣реБрдд рд╕реНрдкрд╖реНрдЯ рд▓рдЧрд╛, рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ рдХреБрдЫ рдФрд░ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреАред рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рдЗрд╕ рдХреЛрдб рдХреЛ "рдЖрдЗрдбрд┐рдпрд╛" рджреНрд╡рд╛рд░рд╛ рд╣рд╛рдЗрд▓рд╛рдЗрдЯ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЬрд┐рд╕рдиреЗ рдореБрдЭреЗ рд╕рд╣реА рд╡рд┐рдЪрд╛рд░ рдХреЗ рд▓рд┐рдП рдкреНрд░реЗрд░рд┐рдд рдХрд┐рдпрд╛, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рдЪрддреБрд░ рд▓рдбрд╝рдХреА рдЖрдорддреМрд░ рдкрд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рд╕реНрдерд╛рди рдкрд░ рд╢реЙрд░реНрдЯ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдмрджрд▓рдиреЗ рдХрд╛ рд╕реБрдЭрд╛рд╡ рджреЗрддреА рд╣реИ StringBuilder::append рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдХреЗ рд╕рд╛рде StringBuilder::append рдХрд░реЗрдВ, рдЬреЛ рдЫреЛрдЯрд╛ рдФрд░ рдкрдврд╝рдиреЗ рдореЗрдВ рдЖрд╕рд╛рди рд╣реИред


рдЗрд╕ рд╕рд░рд▓реАрдХрд░рдг рдХреЗ рд▓рд┐рдП рдПрдХ рдмрд╛рдзрд╛ StringBuilder.append(CharSequence, int, int) рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣реИред рдпрд╣ рджреЗрдЦрддреЗ рд╣реБрдП рдХрд┐ data.str рдлрд╝реАрд▓реНрдб рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реИ, String.substring(beginIndex, endIndex) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ String.substring(beginIndex, endIndex) рдЖрдк рдЗрд╕рдореЗрдВ рд╕реЗ рдПрдХ рд╡рд┐рдХрд▓реНрдк рдЪреБрди рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ StringBuilder.append(String) рдХреЛ рдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


рд░реВрдкрд╛рдВрддрд░рдг рдХреЗ рдмрд╛рдж рдХреЛрдб:


 public String appendBounds(Data data) { int beginIndex = data.beginIndex; int endIndex = data.endIndex; String subString = data.str.substring(beginIndex, endIndex); return new StringBuilder() .append('L') .append(subString) .append(';') .toString(); } 

рдФрд░ рдЕрдм рдЖрдЗрдбрд┐рдпрд╛ рдПрдХ рд╕рд░рд▓реАрдХрд░рдг рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ:


 public String appendBounds(Data data) { int beginIndex = data.beginIndex; int endIndex = data.endIndex; return 'L' + data.str.substring(beginIndex, endIndex) + ';'; } 

рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рд╣рдорд╛рд░рд╛ рд▓рдХреНрд╖реНрдп рдЙрддреНрдкрд╛рджрдХрддрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдЗрддрдиреА рдкрдардиреАрдпрддрд╛ рдирд╣реАрдВ рд╣реИред рджреЛрдиреЛрдВ рддрд░реАрдХреЛрдВ рдХреА рддреБрд▓рдирд╛ рдХрд░реЗрдВ:


 @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) @Fork(jvmArgsAppend = {"-Xms2g", "-Xmx2g"}) public class StringBuilderAppendBenchmark { @Benchmark public String appendSubString(Data data) { String latinStr = data.latinStr; String nonLatinStr = data.nonLatinStr; int beginIndex = data.beginIndex; int endIndex = data.endIndex; String substring = data.nonLatin ? nonLatinStr.substring(beginIndex, endIndex) : latinStr.substring(beginIndex, endIndex); return new StringBuilder() .append('L') .append(substring) .append(';') .toString(); } @Benchmark public String appendBounds(Data data) { String latinStr = data.latinStr; String nonLatinStr = data.nonLatinStr; int beginIndex = data.beginIndex; int endIndex = data.endIndex; String appended = data.nonLatin ? nonLatinStr : latinStr; return new StringBuilder() .append('L') .append(appended, beginIndex, endIndex) .append(';') .toString(); } @State(Scope.Thread) public static class Data { String latinStr; String nonLatinStr; @Param({"true", "false"}) boolean nonLatin; @Param({"5", "10", "50", "100", "500", "1000"}) private int length; private int beginIndex; private int endIndex; private ThreadLocalRandom random = ThreadLocalRandom.current(); @Setup public void setup() { latinStr = randomString("abcdefghijklmnopqrstuvwxyz"); nonLatinStr = randomString(""); beginIndex = 1; endIndex = length + 1; } private String randomString(String alphabet) { char[] chars = alphabet.toCharArray(); StringBuilder sb = new StringBuilder(length + 2); for (int i = 0; i < length + 2; i++) { char c = chars[random.nextInt(chars.length)]; sb.append(c); } return sb.toString(); } } } 

рдмреЗрдВрдЪрдорд╛рд░реНрдХ рджреЛ рдкреЗрдиреА рдХреЗ рд╕рдорд╛рди рд╕рд░рд▓ рд╣реИ: рдПрдХ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рд╕реНрдЯреНрд░рд┐рдВрдЧрдмрд░реНрдмреНрдпреВрд▓ рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЖрдХрд╛рд░ length рдХреНрд╖реЗрддреНрд░ рджреНрд╡рд╛рд░рд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдЬрдм рд╕реЗ рдпрд╛рд░реНрдб 2019 рд╣реИ, рддреЛ рдЖрдкрдХреЛ рдЗрд╕реЗ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рд░реВрдк рдореЗрдВ рдЬрд╛рдВрдЪрдирд╛ рд╣реЛрдЧрд╛ рдЬрд┐рд╕рдореЗрдВ рдореБрдЦреНрдп рд▓реИрдЯрд┐рди рд╡рд░реНрдгрдорд╛рд▓рд╛ (рддрдерд╛рдХрдерд┐рдд рд╕рдВрдкреАрдбрд╝рд┐рдд рд▓рд╛рдЗрди), рдЬрд┐рд╕рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдЪрд░рд┐рддреНрд░ рдХреЗ рдЕрдХреНрд╖рд░ рд╣реЛрддреЗ рд╣реИрдВред 1 рдмрд╛рдЗрдЯ рд╕реЗ рдореЗрд▓ рдЦрд╛рддреА рд╣реИ), рдФрд░ рдЧреИрд░-рд▓реИрдЯрд┐рди рд╡рд░реНрдгреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ (рдкреНрд░рддреНрдпреЗрдХ рдЪрд░рд┐рддреНрд░ 2 рдмрд╛рдЗрдЯреНрд╕ рджреНрд╡рд╛рд░рд╛ рджрд░реНрд╢рд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ)ред


рдПрдХ рд╕рд░рд╕рд░реА рдкрд░реАрдХреНрд╖рд╛ рдкрд░, appendSubString рд╡рд┐рдзрд┐ рд╣рдореЗрдВ рдзреАрдореА appendSubString рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ appendBounds рд╡рд┐рдзрд┐ рдХреЗ рд╕рд╛рде рдЪрд┐рдкрдХреЗ рд╣реБрдП рдбреЗрдЯрд╛ рдХреА рдорд╛рддреНрд░рд╛ рдХреЛ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐, appendSubString рд╡рд┐рдзрд┐ рдореЗрдВ рдПрдХ appendSubString рдПрдХ рд╕реНрдкрд╖реНрдЯ рдирд┐рд░реНрдорд╛рдг рднреА рд╣реИ, рдЕрд░реНрдерд╛рддреН, рдПрдХ рдирдИ рд╡рд╕реНрддреБ рдХреЗ рд▓рд┐рдП рдореЗрдореЛрд░реА рдЖрд╡рдВрдЯрд┐рдд рдХрд░рдирд╛ рдФрд░ data.latinStr рд╕реЗ рд╕рд╛рдордЧреНрд░реА рдХреА рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдмрдирд╛рдирд╛ред / data.nonLatinStr ред


рд╕рднреА рдЕрдзрд┐рдХ рдЖрд╢реНрдЪрд░реНрдпрдЬрдирдХ (рд▓реЗрдХрд┐рди рдХреЗрд╡рд▓ рдкрд╣рд▓реА рдирдЬрд╝рд░ рдореЗрдВ) рдПрдХ рдШрд░реЗрд▓реВ рдорд╢реАрди (рдЗрдВрдЯреЗрд▓ рдХреЛрд░ i5-4690, 3.50 GHz) рдкрд░ JDK11 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдореЗрд░реЗ рджреНрд╡рд╛рд░рд╛ рдХрд┐рдП рдЧрдП рдорд╛рдк рдХреЗ рдкрд░рд┐рдгрд╛рдо рдкреНрд░рддреАрдд рд╣реЛрддреЗ рд╣реИрдВ:


 Benchmark nonLatin length Score Error Units appendBounds true 5 44,6 ┬▒ 0,4 ns/op appendBounds true 10 45,7 ┬▒ 0,7 ns/op appendBounds true 50 129,0 ┬▒ 0,5 ns/op appendBounds true 100 218,7 ┬▒ 0,8 ns/op appendBounds true 500 907,1 ┬▒ 5,5 ns/op appendBounds true 1000 1626,4 ┬▒ 13,0 ns/op appendSubString true 5 28,6 ┬▒ 0,2 ns/op appendSubString true 10 30,8 ┬▒ 0,2 ns/op appendSubString true 50 65,6 ┬▒ 0,4 ns/op appendSubString true 100 106,6 ┬▒ 0,6 ns/op appendSubString true 500 430,1 ┬▒ 2,4 ns/op appendSubString true 1000 839,1 ┬▒ 8,6 ns/op appendBounds:┬╖gc.alloc.rate.norm true 5 184,0 ┬▒ 0,0 B/op appendBounds:┬╖gc.alloc.rate.norm true 10 200,0 ┬▒ 0,0 B/op appendBounds:┬╖gc.alloc.rate.norm true 50 688,0 ┬▒ 0,0 B/op appendBounds:┬╖gc.alloc.rate.norm true 100 1192,0 ┬▒ 0,0 B/op appendBounds:┬╖gc.alloc.rate.norm true 500 5192,0 ┬▒ 0,0 B/op appendBounds:┬╖gc.alloc.rate.norm true 1000 10200,0 ┬▒ 0,0 B/op appendSubString:┬╖gc.alloc.rate.norm true 5 136,0 ┬▒ 0,0 B/op appendSubString:┬╖gc.alloc.rate.norm true 10 160,0 ┬▒ 0,0 B/op appendSubString:┬╖gc.alloc.rate.norm true 50 360,0 ┬▒ 0,0 B/op appendSubString:┬╖gc.alloc.rate.norm true 100 608,0 ┬▒ 0,0 B/op appendSubString:┬╖gc.alloc.rate.norm true 500 2608,0 ┬▒ 0,0 B/op appendSubString:┬╖gc.alloc.rate.norm true 1000 5104,0 ┬▒ 0,0 B/op appendBounds false 5 20,8 ┬▒ 0,1 ns/op appendBounds false 10 24,0 ┬▒ 0,2 ns/op appendBounds false 50 66,4 ┬▒ 0,4 ns/op appendBounds false 100 111,0 ┬▒ 0,8 ns/op appendBounds false 500 419,2 ┬▒ 2,7 ns/op appendBounds false 1000 840,4 ┬▒ 7,8 ns/op appendSubString false 5 25,3 ┬▒ 0,3 ns/op appendSubString false 10 25,7 ┬▒ 0,2 ns/op appendSubString false 50 36,0 ┬▒ 0,1 ns/op appendSubString false 100 52,8 ┬▒ 0,4 ns/op appendSubString false 500 206,1 ┬▒ 6,1 ns/op appendSubString false 1000 388,1 ┬▒ 1,6 ns/op appendBounds:┬╖gc.alloc.rate.norm false 5 80,0 ┬▒ 0,0 B/op appendBounds:┬╖gc.alloc.rate.norm false 10 88,0 ┬▒ 0,0 B/op appendBounds:┬╖gc.alloc.rate.norm false 50 320,0 ┬▒ 0,0 B/op appendBounds:┬╖gc.alloc.rate.norm false 100 544,0 ┬▒ 0,0 B/op appendBounds:┬╖gc.alloc.rate.norm false 500 2144,0 ┬▒ 0,0 B/op appendBounds:┬╖gc.alloc.rate.norm false 1000 4152,0 ┬▒ 0,0 B/op appendSubString:┬╖gc.alloc.rate.norm false 5 96,0 ┬▒ 0,0 B/op appendSubString:┬╖gc.alloc.rate.norm false 10 112,0 ┬▒ 0,0 B/op appendSubString:┬╖gc.alloc.rate.norm false 50 192,0 ┬▒ 0,0 B/op appendSubString:┬╖gc.alloc.rate.norm false 100 288,0 ┬▒ 0,0 B/op appendSubString:┬╖gc.alloc.rate.norm false 500 1088,0 ┬▒ 0,0 B/op appendSubString:┬╖gc.alloc.rate.norm false 1000 2088,0 ┬▒ 0,0 B/op 

рд╣рдорд╛рд░реА рдзрд╛рд░рдгрд╛ рдХрд╛ рдЦрдВрдбрди рдХрд░рддреЗ рд╣реБрдП, рдЕрдзрд┐рдХрд╛рдВрд╢ рдорд╛рдорд▓реЛрдВ рдореЗрдВ (рдиреЙрди-рд▓реИрдЯрд┐рди рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреЗ рд▓рд┐рдП рд╣рдореЗрд╢рд╛ рд╕рд╣рд┐рдд) appendSubString рд╡рд┐рдзрд┐ рддреЗрдЬреА рд╕реЗ рдФрд░ рдХрдо рдЧреНрд▓реВрдЯреЛрдирд╕ (рднрд▓реЗ рд╣реА String::substring рдПрдХ рдирдИ рд╡рд╕реНрддреБ рджреЗрддрд╛ рд╣реИ) рдирд┐рдХрд▓рд╛ред рдпрд╣ рдХреИрд╕реЗ рд╣реБрдЖ?


рдореИрдВ рдХрд┐рддрд╛рдм рдореЗрдВ рджреЗрдЦрддрд╛ рд╣реВрдВ, рдореБрдЭреЗ рдПрдХ рдЕрдВрдЬреАрд░ рджрд┐рдЦрд╛рдИ рджреЗрддреА рд╣реИ


StringBuilder рд╕реНрд░реЛрдд рдХреЛрдб рдХрд╛ рдЕрдзреНрдпрдпрди рдХрд░рдиреЗ рд╕реЗ рдЧреЛрдкрдиреАрдпрддрд╛ StringBuilder рдкрд░реНрджрд╛ StringBuilder рдорджрдж рдорд┐рд▓реЗрдЧреАред рджреЛрдиреЛрдВ рдЙрдкрдпреЛрдЧ рдХреА рдЧрдИ рд╡рд┐рдзрд┐рдпрд╛рдБ AbstractStringBuilder рдХреЗ рд╕рдорд╛рди рддрд░реАрдХреЛрдВ рд╕реЗ рдХреЙрд▓ рдкрд╛рд╕ рдХрд░рддреА рд╣реИрдВ:


 public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, Comparable<StringBuilder>, CharSequence { @Override public StringBuilder append(String str) { super.append(str); return this; } @Override public StringBuilder append(CharSequence s, int start, int end) { super.append(s, start, end); return this; } } 

AbstractStringBuilder.append(String) :


 public AbstractStringBuilder append(String str) { if (str == null) { return appendNull(); } int len = str.length(); ensureCapacityInternal(count + len); putStringAt(count, str); count += len; return this; } private final void putStringAt(int index, String str) { if (getCoder() != str.coder()) { inflate(); } str.getBytes(value, index, coder); } 

рдпрд╣рд╛рдБ рдХреНрдпрд╛ рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ? AbstractStringBuilder::inflate рдирд╛рдо рдХреЗ рд░реВрдк рдореЗрдВ AbstractStringBuilder::inflate , рдЕрд╕рдорд╛рди рддрд╛рд░ рдХрд╛ рд╕рдВрдпреЛрдЬрди рдХрд░рддреЗ рд╕рдордп AbstractStringBuilder.value рд╕рд░рдгреА рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рддрд╛ рд╣реИред рдбреЗрдЯрд╛ рдХреЛ String::getBytes рдореЗрдВ String::getBytes рдЧрдпрд╛ рд╣реИ:


 void getBytes(byte[] dst, int dstBegin, byte coder) { if (coder() == coder) { System.arraycopy(value, 0, dst, dstBegin << coder, value.length); } else { // this.coder == LATIN && coder == UTF16 StringLatin1.inflate(value, 0, dst, dstBegin, value.length); } } 

рдХреНрдпрд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ? рдпрджрд┐ рддрд╛рд░ рд╕рдорд░реВрдк рд╣реЛрддреЗ рд╣реИрдВ, рддреЛ рдЖрдВрддрд░рд┐рдХ System::arraycopy рдХрд╛ рдЙрдкрдпреЛрдЧ рдбреЗрдЯрд╛ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЕрдиреНрдпрдерд╛ StringLatin1::inflate рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рдордВрдбрд▓ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╣рдореЗрдВ StringUTF16::inflate рдУрд░ рд▓реЗ рдЬрд╛рддрд╛ рд╣реИ:


 // inflatedCopy byte[] -> byte[] @HotSpotIntrinsicCandidate public static void inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len) { // We need a range check here because 'putChar' has no checks checkBoundsOffCount(dstOff, len, dst); for (int i = 0; i < len; i++) { putChar(dst, dstOff++, src[srcOff++] & 0xff); } } @HotSpotIntrinsicCandidate static void putChar(byte[] val, int index, int c) { assert index >= 0 && index < length(val) : "Trusted caller missed bounds check"; index <<= 1; val[index++] = (byte)(c >> HI_BYTE_SHIFT); val[index] = (byte)(c >> LO_BYTE_SHIFT); } 

рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдпрджрд┐ рдкрдВрдХреНрддрд┐рдпрд╛рдБ рд╕рдЬрд╛рддреАрдп рд╣реИрдВ, рддреЛ рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо-рдЖрд╢реНрд░рд┐рдд рд╡рд┐рдзрд┐ System::arraycopy рдХреЛ рдбреЗрдЯрд╛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЕрдиреНрдпрдерд╛ рдПрдХ рд▓реВрдк (рдЖрдВрддрд░рд┐рдХ рднреА) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рдЬрдм рджреЛ рд▓рд╛рдЗрдиреЛрдВ рдХреЛ рдЧреНрд▓реВрдЗрдВрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЬрд╣рд╛рдВ рд╕рднреА рд╡рд░реНрдг рдореБрдЦреНрдп рд▓реИрдЯрд┐рди рд╡рд░реНрдгрдорд╛рд▓рд╛ рдХреЗ рд╕реЗрдЯ рдореЗрдВ рд╣реЛрддреЗ рд╣реИрдВ (рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, 1 рдмрд╛рдЗрдЯ рдореЗрдВ рдлрд┐рдЯ рд╣реЛрддреЗ рд╣реИрдВ), рддреЛ рдкреНрд░рджрд░реНрд╢рди рд╡рд┐рд╖рдо рд▓рд╛рдЗрдиреЛрдВ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдмрд╣реБрдд рдмреЗрд╣рддрд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдЗрд╕рдХреА рдкреБрд╖реНрдЯрд┐ рдХрд░рддрд╛ рд╣реИ ( nonLatin = false рд▓рд┐рдП рдЖрдЙрдЯрдкреБрдЯ рджреЗрдЦреЗрдВ)ред


рдЕрдм AbstractStringBuilder.append(CharSequence, int, int) рд╡рд┐рдзрд┐ AbstractStringBuilder.append(CharSequence, int, int) :


 @Override public AbstractStringBuilder append(CharSequence s, int start, int end) { if (s == null) { s = "null"; } checkRange(start, end, s.length()); int len = end - start; ensureCapacityInternal(count + len); appendChars(s, start, end); return this; } private final void appendChars(CharSequence s, int off, int end) { if (isLatin1()) { byte[] val = this.value; for (int i = off, j = count; i < end; i++) { char c = s.charAt(i); if (StringLatin1.canEncode(c)) { val[j++] = (byte)c; } else { count = j; inflate(); StringUTF16.putCharsSB(this.value, j, s, i, end); count += end - i; return; } } } else { StringUTF16.putCharsSB(this.value, count, s, off, end); } count += end - off; } 

рдпрд╣рд╛рдВ, рджреГрд╖реНрдЯрд┐рдХреЛрдг рдкрд┐рдЫрд▓реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдПрдХ рдХреЗ рд╕рдорд╛рди рд╣реИ: рд╕рдЬрд╛рддреАрдп рддрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП, рдПрдХ рд╕рд░рд▓ рддрдВрддреНрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдпрд╣рд╛рдВ, рдПрдХ рдкрд╛рд╢ рдореЗрдВ рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рд╕рд╛рдЗрди рдЗрди рдХрд░реЗрдВ), рд╡рд┐рд╖рдо рддрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП рд╣рдо StringUTF16 рдЙрдкрдпреЛрдЧ StringUTF16 , рд╣рд╛рд▓рд╛рдВрдХрд┐, рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ StringUTF16::putCharsSB рдЖрдВрддрд░рд┐рдХ рдирд╣реАрдВ рдХрд╣рд╛ рдЧрдпрд╛ StringUTF16::putCharsSB ред


 public static void putCharsSB(byte[] val, int index, CharSequence s, int off, int end) { checkBoundsBeginEnd(index, index + end - off, val); for (int i = off; i < end; i++) { putChar(val, index++, s.charAt(i)); } } 

рддреЛ, рджреЛрдиреЛрдВ рддрд░реАрдХреЛрдВ рдХреА рдЖрдВрддрд░рд┐рдХ рд╕рдВрд░рдЪрдирд╛ рдФрд░ рдЙрдирдХреЗ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдкреНрд░рджрд░реНрд╢рди рдХрд╛ рдХрд╛рд░рдг рдХрдореЛрдмреЗрд╢ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рд╕реНрдкрд╖реНрдЯ рд╣реИред рд╕рд╡рд╛рд▓ рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ рдЙрдарддрд╛ рд╣реИ - рдЖрдЧреЗ рдкреНрд░рд╛рдкреНрдд рдЬреНрдЮрд╛рди рдХреЗ рд╕рд╛рде рдХреНрдпрд╛ рдХрд░рдирд╛ рд╣реИ? рдПрдХ рд╕рд╛рде рдХрдИ рд╡рд┐рдХрд▓реНрдк рд╣реИрдВ:


1) рдЗрд╕реЗ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦреЗрдВ рдФрд░ рдЬрдм рдпрд╣ рдПрдХ рд╕рдВрджрд┐рдЧреНрдз рдХреЛрдб рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рддрд╛ рд╣реИ, рддреЛ рдЗрд╕реЗ рд╣рд╛рде рд╕реЗ рдмрджрд▓ рджреЗрдВ
2) рдЯреИрдЧрд┐рд░ рдХреЗ рдкрд╛рд╕ рдЬрд╛рдУ рдФрд░ рдЙрд╕реЗ рдПрдХ рдЪреЗрдХ рджрд╛рдпрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣реЗрдВ рдЬреЛ рд╣рдорд╛рд░реЗ рдмрдЬрд╛рдп рдХрд╛рдо рдХрд░реЗрдЧрд╛
3) рдЬреЗрдбреАрдХреЗ рдореЗрдВ рдмрджрд▓рд╛рд╡ рдХрд░реЗрдВ рддрд╛рдХрд┐ рдХреЛрдб рдмрд┐рд▓реНрдХреБрд▓ рднреА рди рдмрджрд▓реЗред


рдмреЗрд╢рдХ, рд╣рдо рддреАрд╕рд░реЗ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред рдореМрдХрд╛ рд▓реЗрдиреЗ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╣реИрдВ?


Deeps рдореЗрдВ рдиреАрдЪреЗ


рд╣рдо рдкреНрд░рд╢рд┐рдХреНрд╖рдг рджреЗрдВрдЧреЗ рдмрд┐рд▓реНрд▓рд┐рдпреЛрдВ рдкрд░ рдЧреНрдпрд╛рд░рд╣рд╡реЗрдВ рдЬрд╛рд╡рд╛ рдХреЗ рд╕реНрд░реЛрдд рдХреЛрдб рдкрд░, рдЖрдк рдпрд╣рд╛рдВ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ ред


рд╕реБрдзрд╛рд░ рдХрд░рдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рд╕рд░рд▓ рдФрд░ рд╕реНрдкрд╖реНрдЯ рддрд░реАрдХрд╛ рд╣реИ рдХрд┐ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА AbstractStringBuilder.append(CharSequence, int, int) рд╡рд┐рдзрд┐ рдХреЗ рдЕрдВрджрд░ рдПрдХ рд╡рд┐рдХрд▓реНрдк рдХрд╛ рдЪрдпрди рдХрд░реЗрдВ:


 //  public AbstractStringBuilder append(CharSequence s, int start, int end) { if (s == null) { s = "null"; } checkRange(start, end, s.length()); int len = end - start; ensureCapacityInternal(count + len); appendChars(s, start, end); return this; } //  public AbstractStringBuilder append(CharSequence s, int start, int end) { if (s == null) { s = "null"; } checkRange(start, end, s.length()); return append(s.subSequence(start, end).toString()); } 

рдЕрдм рдЖрдкрдХреЛ JDK рдмрдирд╛рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ, рдкрд░реАрдХреНрд╖рдг рдЪрд▓рд╛рдПрдВ рдФрд░ рдЙрд╕ рдкрд░ StringBuilderAppendBenchmark::appendBounds рдмреЗрдВрдЪрдорд╛рд░реНрдХ StringBuilderAppendBenchmark::appendBounds , рдЬрд┐рд╕рдХреЗ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреА рддреБрд▓рдирд╛ рдореВрд▓ JDK рдкрд░ рдПрдХ рд╣реА рдмреЗрдВрдЪрдорд╛рд░реНрдХ рдХреЗ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЗ рд╕рд╛рде рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:


 #   before      JDK, # after -   Benchmark nonLatin length before after Units avgt true 5 44,6 64,4 ns/op avgt true 10 45,7 66,3 ns/op avgt true 50 129,0 168,9 ns/op avgt true 100 218,7 281,9 ns/op avgt true 500 907,1 1116,2 ns/op avgt true 1000 1626,4 2002,5 ns/op gc.alloc.rate.norm true 5 184,0 264,0 B/op gc.alloc.rate.norm true 10 200,0 296,0 B/op gc.alloc.rate.norm true 50 688,0 904,0 B/op gc.alloc.rate.norm true 100 1192,0 1552,0 B/op gc.alloc.rate.norm true 500 5192,0 6752,0 B/op gc.alloc.rate.norm true 1000 10200,0 13256,0 B/op avgt false 5 20,8 38,0 ns/op avgt false 10 24,0 37,8 ns/op avgt false 50 66,4 82,9 ns/op avgt false 100 111,0 138,8 ns/op avgt false 500 419,2 531,9 ns/op avgt false 1000 840,4 1002,7 ns/op gc.alloc.rate.norm false 5 80,0 152,0 B/op gc.alloc.rate.norm false 10 88,0 168,0 B/op gc.alloc.rate.norm false 50 320,0 440,0 B/op gc.alloc.rate.norm false 100 544,0 688,0 B/op gc.alloc.rate.norm false 500 2144,0 2688,0 B/op gc.alloc.rate.norm false 1000 4152,0 5192,0 B/op 

рдХреНрдпрд╛ рдХрд╣рддреЗ рд╣реИрдВ, рдЕрдЪрд╛рдирдХ! рд╕реБрдзрд╛рд░ рди рдХреЗрд╡рд▓ рд╣реБрдЖ, рдмрд▓реНрдХрд┐ рдЧрд┐рд░рд╛рд╡рдЯ рднреА рд╣реБрдИред рд▓рд╛рдирдд рд╣реИ, рд▓реЗрдХрд┐рди рдХреИрд╕реЗ?


рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рдмрд╣реБрдд рд╢реБрд░реБрдЖрдд рдореЗрдВ, StringBuilder::append рд╡рд┐рдзрд┐ рдХреЗ рд╡рд┐рд╡рд░рдг рдореЗрдВ StringBuilder::append рдореИрдВрдиреЗ рдПрдХ рдЫреЛрдЯреА, рд▓реЗрдХрд┐рди рдЧрдВрднреАрд░ рд░реВрдк рд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЪреВрдХ рдХреАред рд╡рд┐рдзрд┐ рдЗрд╕ рддрд░рд╣ рд╡рд░реНрдгрд┐рдд рдереА:


 public final class StringBuilder { @Override public StringBuilder append(String str) { super.append(str); return this; } } 

рдФрд░ рдпрд╣рд╛рдБ рдЗрд╕рдХрд╛ рдкреВрд░рд╛ рджреГрд╢реНрдп рд╣реИ:


 public final class StringBuilder { @Override @HotSpotIntrinsicCandidate public StringBuilder append(String str) { super.append(str); return this; } } 

рдЬрд╛рд╡рд╛ рдХреЛрдб рдЬрд┐рд╕реЗ рд╣рдордиреЗ рдКрдкрд░ рдЬрд╛рдВрдЪрд╛, рд╕реА 2 рд╕реНрддрд░ рдкрд░ рдЧрд░реНрдо рдФрд░ рд╕рдВрдХрд▓рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛, рдЗрд╕рд╕реЗ рдХреЛрдИ рдлрд░реНрдХ рдирд╣реАрдВ рдкрдбрд╝рддрд╛, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЖрдВрддрд░рд┐рдХред рдпрд╣ async-profiler рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдХреЛ рд╣рдЯрд╛рдХрд░ рд╕рд╛рдмрд┐рдд рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реИред рдЗрд╕рдХреЗ рдмрд╛рдж, рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдХреЛ length = 1000 рдФрд░ nonLatin = true - nonLatin = true рд▓рд┐рдП рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ nonLatin = true :


 #   `appendSubString`, JDK    ns percent samples top ---------- ------- ------- --- 19096340914 43.57% 1897673 jbyte_disjoint_arraycopy <--------- 13500185356 30.80% 1343343 jshort_disjoint_arraycopy <--------- 4124818581 9.41% 409533 java.lang.String.<init> #   2177311938 4.97% 216375 java.lang.StringUTF16.compress #   1557269661 3.55% 154253 java.util.Arrays.copyOfRange #   349344451 0.80% 34823 appendSubString_avgt_jmhStub 279803769 0.64% 27862 java.lang.StringUTF16.newString 274388920 0.63% 27312 org.openjdk.jmh.infra.Blackhole.consume 160962540 0.37% 15946 SpinPause 122418222 0.28% 11795 __memset_avx2 

StringBuilder (рдФрд░ AbstractStringBuilder ) рдХрд╛ рдХреЛрдб рдпрд╣рд╛рдВ рднреА рдЧрдВрдз рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓ рдХреЗ рд▓рдЧрднрдЧ 3/4 рдкрд░ рдПрдХ рдЖрдВрддрд░рд┐рдХ рджреНрд╡рд╛рд░рд╛ рдХрдмреНрдЬрд╛ рдХрд░ рд▓рд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдореИрдВ рд╣рдорд╛рд░реЗ "рдмреЗрд╣рддрд░" StringBuilder.append(CharSequence, int, int) рдХреЗ рдкреНрд░реЛрдлрд╛рдЗрд▓ рдореЗрдВ рдПрдХ рд╣реА рддрд╕реНрд╡реАрд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд┐рд░реАрдХреНрд╖рдг рдХрд░рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ред


рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдпрд╣ рд╣реИ:


  ns percent samples top ---------- ------- ------- --- 19071221451 43.78% 1897827 jbyte_disjoint_arraycopy 6409223440 14.71% 638348 jlong_disjoint_arraycopy 3933622128 9.03% 387403 java.lang.StringUTF16.newBytesFor 2067248311 4.75% 204193 java.lang.AbstractStringBuilder.ensureCapacityInternal 1929218737 4.43% 194751 java.lang.StringUTF16.compress 1678321343 3.85% 166458 java.util.Arrays.copyOfRange 1621470408 3.72% 160849 java.lang.String.checkIndex 969180099 2.22% 96018 java.util.Arrays.copyOf 581600786 1.34% 57818 java.lang.AbstractStringBuilder.<init> 417818533 0.96% 41611 appendBounds_jmhTest 406565329 0.93% 40479 java.lang.String.<init> 340972882 0.78% 33727 java.lang.AbstractStringBuilder.append 299895915 0.69% 29982 java.lang.StringBuilder.toString 183885595 0.42% 18136 SpinPause 168666033 0.39% 16755 org.openjdk.jmh.infra.Blackhole.consume 

рдЖрдк рдХрд╣реЗрдВрдЧреЗ: "рд╡реЗ рдпрд╣рд╛рдБ рд╣реИрдВ, рдЖрдВрддрд░рд┐рдХ, рдмрд╣реБрдд рдКрдкрд░!" рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдХреЗрд╡рд▓ рдпреЗ рдПрдХ рд╣реА рдЖрдВрддрд░рд┐рдХ рдирд╣реАрдВ рд╣реИрдВ (рдКрдкрд░ рд╕реЗ рджреВрд╕рд░реЗ рдХреЗ рдирд╛рдо рдХреА рддреБрд▓рдирд╛ рдХрд░реЗрдВ)ред рдпрд╛рдж:


 public final class StringBuilder { @Override @HotSpotIntrinsicCandidate public StringBuilder append(String str) { super.append(str); return this; } } 

рдпрд╣рд╛рдБ рдЖрдВрддрд░рд┐рдХ рдХреЙрд▓ StringBuilder.append(String) рдХреЛ рдмрджрд▓ рджреЗрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдорд╛рд░реЗ рдкреИрдЪ рдореЗрдВ рдпрд╣ рдХреЙрд▓ рдирд╣реАрдВ рд╣реИ! рдЬрд┐рд╕реЗ AbstractStringBuilder.append(String) рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред jbyte_disjoint_arraycopy рдХреЙрд▓ рдЬрд┐рд╕реЗ рд╣рдо jbyte_disjoint_arraycopy , рд╡рд╣ StringLatin1::inflate рд▓рд┐рдП рдЖрдВрддрд░рд┐рдХ рд╣реИ, рдЬрд┐рд╕реЗ AbstractStringBuider::putStringAt рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ AbstractStringBuider::putStringAt рдорд╛рдзреНрдпрдо рд╕реЗ String::getBytes ред рдпрд╣реА рд╣реИ, StringBuilder::append рд╡рд┐рдкрд░реАрдд StringBuilder::append рди рдХреЗрд╡рд▓ рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо-рд╡рд┐рд╢рд┐рд╖реНрдЯ, рдмрд▓реНрдХрд┐ рдЬрд╛рд╡рд╛ рдХреЛрдб рднреА рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рддрд╛ рд╣реИ,


рдЕрд╕рдлрд▓рддрд╛ рдХреЗ рдХрд╛рд░рдг рдХреЛ рд╕рдордЭреЗрдВ, рдЕрдиреНрдпрдерд╛ рд╕рдлрд▓ рд╣реЛрдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред рдпрд╣ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдирд╛ рдЖрд╕рд╛рди рд╣реИ рдХрд┐ рд╣рдореЗрдВ рдХрд┐рд╕реА рддрд░рд╣ StringBuilder::append рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдЖрдк рдкрд┐рдЫрд▓реЗ рдкреИрдЪ рдХреЛ рдлрд╛рдбрд╝рдХрд░ рдФрд░ StringBuilder рдЦреБрдж рдмрджрд▓рд╛рд╡ рдХрд░рдХреЗ рдРрд╕рд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


 public final class StringBuilder { //  @Override public StringBuilder append(CharSequence s, int start, int end) { super.append(s, start, end); return this; } //  @Override public StringBuilder append(CharSequence s, int start, int end) { if (s == null) { s = "null"; } checkRange(start, end, s.length()); return this.append(s.subSequence(start, end).toString()); } } 

рдЕрдм рд╕рдм рдХреБрдЫ рд╕рдордЭрджрд╛рд░реА рд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ: рдЖрдВрддрд░рд┐рдХ StringBuilder :: рдкрд░рд┐рд╢рд┐рд╖реНрдЯ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред
рдлрд┐рд░ рд╕реЗ рдмрдирд╛рдПрдБ, рдЪрд▓рд╛рдПрдВ, рддреБрд▓рдирд╛ рдХрд░реЗрдВ:


 #   before      JDK, # after -   Benchmark nonLatin length before after Units avgt true 5 44,6 60,2 ns/op avgt true 10 45,7 59,1 ns/op avgt true 50 129,0 164,6 ns/op avgt true 100 218,7 276,2 ns/op avgt true 500 907,1 1088,8 ns/op avgt true 1000 1626,4 1959,4 ns/op gc.alloc.rate.norm true 5 184,0 264,0 B/op gc.alloc.rate.norm true 10 200,0 296,0 B/op gc.alloc.rate.norm true 50 688,0 904,0 B/op gc.alloc.rate.norm true 100 1192,0 1552,0 B/op gc.alloc.rate.norm true 500 5192,0 6752,0 B/op gc.alloc.rate.norm true 1000 10200,0 13256,0 B/op avgt false 5 20,8 37,9 ns/op avgt false 10 24,0 37,9 ns/op avgt false 50 66,4 80,9 ns/op avgt false 100 111,0 125,6 ns/op avgt false 500 419,2 483,6 ns/op avgt false 1000 840,4 893,8 ns/op gc.alloc.rate.norm false 5 80,0 152,0 B/op gc.alloc.rate.norm false 10 88,0 168,0 B/op gc.alloc.rate.norm false 50 320,0 440,0 B/op gc.alloc.rate.norm false 100 544,0 688,0 B/op gc.alloc.rate.norm false 500 2144,0 2688,0 B/op gc.alloc.rate.norm false 1000 4152,0 5187,2 B/op 

рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдмрд╣реБрдд рджреБрдЦреА рд╣реВрдВ, рд▓реЗрдХрд┐рди рдпрд╣ рдмреЗрд╣рддрд░ рдирд╣реАрдВ рд╣реБрдЖред рдЕрдм рдПрдХ рдирдпрд╛ рдкреНрд░реЛрдлрд╝рд╛рдЗрд▓:


  ns percent samples top ---------- ------- ------- --- 19614374885 44.12% 1953620 jbyte_disjoint_arraycopy 6645299702 14.95% 662146 jlong_disjoint_arraycopy 4065789919 9.15% 400167 java.lang.StringUTF16.newBytesFor 2374627822 5.34% 234746 java.lang.AbstractStringBuilder.ensureCapacityInternal 1837858014 4.13% 183822 java.lang.StringUTF16.compress 1472039604 3.31% 145956 java.util.Arrays.copyOfRange 1316397864 2.96% 130747 appendBounds_jmhTest 956823151 2.15% 94959 java.util.Arrays.copyOf 573091712 1.29% 56933 java.lang.AbstractStringBuilder.<init> 434454076 0.98% 43202 java.lang.String.<init> 368480388 0.83% 36439 java.lang.AbstractStringBuilder.append 304409057 0.68% 30442 java.lang.StringBuilder.toString 272437989 0.61% 26833 SpinPause 201051696 0.45% 19985 java.lang.StringBuilder.<init> 198934052 0.45% 19810 appendBounds_avgt_jmhStub 

рдереЛрдбрд╝рд╛ рдмрджрд▓ рдЧрдпрд╛ рд╣реИред рдореЗрд░реЗ рд▓рд┐рдП, рдпрд╣ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ рдХрд┐ StringBuilder.append(String) рднреАрддрд░ рд╕реЗ StringBuilder.append(String) рддрдХ StringBuilder.append(String) рд╕рдордп рдЖрдВрддрд░рд┐рдХ рдХрд╛рдо рдХреНрдпреЛрдВ рдирд╣реАрдВ рдХрд┐рдпрд╛ред рдПрдХ рд╕рдВрджреЗрд╣ рд╣реИ рдХрд┐ StringBuilder.append(String) рдкрджреНрдзрддрд┐ рдХреЗ рд╢рд░реАрд░ рдХреЛ StringBuilder.append(CharSequence, int, int) рдХреЗ рд╢рд░реАрд░ рдореЗрдВ рдЪрд┐рдкрдХрд╛рдиреЗ рд╕реЗ рд╡реАрдПрдо рд╡рд┐рдзрд┐ рдХреЙрд▓ рдХреЗ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдХреБрдЫ рдкрд░рд┐рд╡рд░реНрддрди рд╣реЛрддрд╛ рд╣реИред


рд╡реИрд╕реЗ рднреА, рдпрд╣ рдлрд┐рдпрд╛рд╕реНрдХреЛ, рднрд╛рдИ рд╣реИред рдЬреЗрдбреАрдХреЗ рдХреЛ рдкреИрдЪ рдХрд░рдирд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рдерд╛, рд▓реЗрдХрд┐рди рд╣рдо рдЕрднреА рднреА рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд╣рд╛рдВ рдпрд╣ рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИред


рд╡рд┐рдлрд▓рддрд╛ рд╕рд╛рд╣рд┐рддреНрдпрд┐рдХ рд╡рд╛рдкрд╕реА
рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдПрдиреНрдХреНрд░рд┐рдкреНрд╢рди рджреЛ рджрд┐рдиреЛрдВ рдореЗрдВ рдЖрдпрд╛ред рдирд╛рд╡рд┐рдХ рдУрдЯреЛ рд╡реЗрд▓рд╛рд░рд╛ рдХреЗ рд╕рд╛рде рднрд╛рдЧ рдирд╣реАрдВ рд▓реЗрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИ, рдПрдХ рдХрдВрдкрдиреА рдХреЗ рд╕рд╛рде рдЬреЛ рдЖрд╢реНрдЪрд░реНрдпрдЬрдирдХ рд░реВрдк рд╕реЗ рддреЗрдЬ рдФрд░ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдпреБрджреНрдзрдкреЛрддреЛрдВ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рддреА рд╣реИред рдирд╛рд╡рд┐рдХ рдореЗрд░реЗ рд▓рд┐рдП рдПрдиреНрдХреНрд░рд┐рдкреНрд╢рди рдкрдврд╝рдирд╛ рдирд╣реАрдВ рдЪрд╛рд╣рддрд╛ рд╣реИред рд╡рд╣ рдХреЗрд╡рд▓ рдХрдорд╛рдВрдб рдкреЛрд╕реНрдЯ рд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рджреЛрд╣рд░рд╛рддрд╛ рд╣реИ: "рдирд╣реАрдВред" рдПрдиреНрдХреНрд░рд┐рдкреНрд╢рди рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ "рдХреНрдпреЛрдВ рдирд╣реАрдВред" "рдирд╣реАрдВ" рдХрд┐рд╕реА рднреА рдорд╛рдорд▓реЗ рдореЗрдВ рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рд╡рд╣ рдПрдХ рдмрдбрд╝реЗ рдХрдВрдкреНрдпреВрдЯрд░ рдХреЗ рд▓рд┐рдП рдЬрд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрджрд┐ рдЙрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреБрдЫ рднреА рдирд╣реАрдВ рдкрддрд╛ рдерд╛, рддреЛ рдЗрд╕рдХрд╛ рдЬрд╡рд╛рдм рд╣рд╛рдВ рдореЗрдВ рд╣реЛрдЧрд╛: рдЗрд╕реЗ рдЖрдЬрд╝рдорд╛рдПрдВред рдмрд╣реБрдд рдмреБрд░рд╛ред рдРрд╕реЗ рджрд┐рд▓рдЪрд╕реНрдк рд╡реНрдпрдХреНрддрд┐ рдХреЛ рдЦреЛрдирд╛ рдПрдХ рджрдпрд╛ рд╣реИред рдФрд░ рд╕реЗрдирд╛рдкрддрд┐ рдореБрдЭреЗ рдХреНрд╖рдорд╛ рдХрд░реЗрдВред рд╢рд╛рдпрдж рдкрд╣рд▓реА рдмрд╛рд░ рдЕрдлрд╝рд╕реЛрд╕ рд╣реБрдЖред рд╡рд╣ рдореБрдЭреЗ рд╡рд╛рдЗрдХрд┐рдВрдЧреНрд╕ рдореЗрдВ рдШреБрд╕рддреЗ рд╣реБрдП рджреЗрдЦрддрд╛ рд╣реИред рдФрд░ рд╡рд╣ рдореБрдЭреЗ рдлрд┐рд░ рд╕реЗ рдЧреНрд░реЗрд╣рд╛рдЙрдВрдб рдореЗрдВ рдзрдХреЗрд▓рдирд╛ рдирд╣реАрдВ рдЪрд╛рд╣рддрд╛ рд╣реИред
рд╡рд╣ рдЪреБрдк рд╣реИред рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдкрддрд╛ рд╣реИ рдХрд┐ рд╢реНрд░рдорд┐рдХреЛрдВ рдХреА рдПрдХ рдЬрдВрдЧрд▓реА рдХрдореА рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдореЗрдВ:
- рдореИрдВ, рдХреЙрдорд░реЗрдб рдЬрдирд░рд▓, рдХрд▓ рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реВрдВред рдореБрдЭреЗ рдЬрд╛рдиреЗ рджреЛ?
- рдЪрд▓реЗрдВред - рдФрд░ рдЕрдЪрд╛рдирдХ рд╡рд╣ рдореБрд╕реНрдХреБрд░рд╛рддреА рд╣реИред "рддреБрдореНрд╣реЗрдВ рдкрддрд╛ рд╣реИ, рд╣рд░ рдмрд╛рджрд▓ рдореЗрдВ рдПрдХ рдЪрд╛рдВрджреА рдХреА рдкрд░рдд рд╣реЛрддреА рд╣реИред"
", рдХреЙрдорд░реЗрдб рдЬрдирд░рд▓, рд╣рдореЗрд╢рд╛ рдЕрдЪреНрдЫреЗ рдХреЗ рдмрд┐рдирд╛ рдмреАрдорд╛рд░ рд╣реИрдВред"
"рдФрд░ рдпрд╣рд╛рдБ рдпрд╣ рд╣реИред" рдЖрдкрдХреЛ рдЙрд╕рд╕реЗ рдорд┐рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдордирд╛ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдпрд╣ рдмреБрд░рд╛ рд╣реИред рд▓реЗрдХрд┐рди рдЕрдкрдиреЗ рдЕрдиреБрднрд╡ рдХреЗ рдЦрдЬрд╛рдиреЗ рдореЗрдВ, рд╣рдордиреЗ рдПрдХ рдФрд░ рдЕрдирд╛рдЬ рдЬреЛрдбрд╝рд╛ред

рдирд┐рд╖реНрдХрд░реНрд╖:


  • рдХреБрдЫ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдЬреЗрдбреАрдХреЗ рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдХреЛрдб рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рд▓рд┐рдП рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╡рд┐рдзрд┐ рдХреЗ рд╢рд░реАрд░ рдХреЗ рдмрдЬрд╛рдп рдПрдХ рдЖрдВрддрд░рд┐рдХ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬреЛ рд╡реАрдПрдо рдХреЗ рдЖрдВрддреЛрдВ рдореЗрдВ рдЫрд┐рдкрд╛ рд╣реБрдЖ рд╣реИред
  • рдЗрд╕реА рддрд░рд╣ рдХреЗ рддрд░реАрдХреЛрдВ рдХреЛ рдкрд╣рдЪрд╛рдирд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ, @HotSpotIntrinsicCandidate рд▓реЗрдмрд▓ рдЙрдиреНрд╣реЗрдВ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдХреБрдЫ рддрд░реАрдХреЛрдВ рдХреЛ рдмрд┐рдирд╛ рдХрд┐рд╕реА рд╕рдВрдХреЗрдд рдХреЗ рдЖрдВрддрд░рд┐рдХ рд░реВрдк рд╕реЗ @HotSpotIntrinsicCandidate рдЬрд╛рддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП String::equals (рдФрд░ рдХрдИ, рдХрдИ рдЕрдиреНрдп )ред
  • рдкрд╣рд▓реЗ рджреЛ рд╕реЗ рдЬреЛ рдирд┐рд╖реНрдХрд░реНрд╖ рдирд┐рдХрд▓рддрд╛ рд╣реИ рд╡рд╣ рдпрд╣ рд╣реИ рдХрд┐ рдЬреЗрдбреАрдХреЗ рдХреЛрдб рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╣рдорд╛рд░реА рдЪрд░реНрдЪрд╛ рд╡рд╛рд╕реНрддрд╡рд┐рдХрддрд╛ рдХреЗ рд╡рд┐рдкрд░реАрдд рд╣реЛ рд╕рдХрддреА рд╣реИред C'est la vie

рдкреБрдирд╢реНрдЪ
рдПрдХ рдФрд░ рд╕рдВрднрд╛рд╡рд┐рдд рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрди:


 StringBuilder sb = new StringBuilder(); sb.append(str, 0, endIndex); // --> StringBuilder sb = new StringBuilder(str.substring(o, endIndex)); 

рдкреА рдкреА рдПрд╕
рдУрд░реЗрдХрд▓ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдареАрдХ рд╣реА рдЗрдВрдЧрд┐рдд рдХрд░рддреЗ рд╣реИрдВ


рдпрд╣ рдПрдХ рдХреЛрдб рдкрде рдореЗрдВ рдкреЗрд╢ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рдореБрдЭреЗ рдЕрдЬреАрдм рдФрд░ рдЖрд╢реНрдЪрд░реНрдпрдЬрдирдХ рд▓рдЧрддрд╛ рд╣реИ
sb.append (рд╕реАрдПрд╕, рдЗрдВрдЯ, рдЗрдВрдЯ) рдЬреЛ рд╕реНрдореГрддрд┐ рдХреЛ рдЖрд╡рдВрдЯрд┐рдд рдХрд░рддрд╛ рд╣реИ рддрд╛рдХрд┐ рдЖрдВрддрд░рд┐рдХ рд░реВрдк рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗ
рдХреЗрд╡рд▓ рдХрднреА-рдХрднреА рдЪреАрдЬреЗрдВ рддреЗрдЬреА рд╕реЗ рдЪрд▓рддреА рд╣реИрдВред рдЬреИрд╕рд╛ рдХрд┐ рдЖрдкрдиреЗ рджреЗрдЦрд╛, рдкреНрд░рджрд░реНрд╢рди
рдЯреНрд░реЗрдбрдСрдлрд╝ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИрдВред

рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рдпрджрд┐ рд╣рдо sb.append (cs, int, int) рдХреЛ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рддреЛ рд╢рд╛рдпрдж рд╣рдореЗрдВ рдмрд╕ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП
рдЖрдЧреЗ рдФрд░ рдХрд░реЗрдВ, рд╕рдВрднрд╡рддрдГ рдЖрдВрддрд░рд┐рдХ рд░реВрдк рд╕реЗ рдЬреЛрдбрд╝рдХрд░ рдпрд╛ рдкреБрдирд░реНрд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░рдХреЗред

рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рд╕рдорд╛рдзрд╛рди StringBuilder.append(CharSequence, int, int) ред


тЖТ рдХрд╛рд░реНрдп
тЖТ рдЪрд░реНрдЪрд╛


рдкреА рдкреА рдПрд╕
рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ, рдЗрд╕ рд╕рдордп, рдЬрдм рдХреБрдЫ рд▓рд┐рдЦрдирд╛ рдкрд╕рдВрдж рд╣реИ


 StringBuilder sb = new StringBuilder(); sb.append(str.substring(0, endIndex)); 

"рдЖрдЗрдбрд┐рдпрд╛" рд╕реЗ рдХреЛрдб рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХрд╛ рд╕реБрдЭрд╛рд╡ рдорд┐рд▓рддрд╛ рд╣реИ


 StringBuilder sb = new StringBuilder(); sb.append(s, 0, endIndex); 

рдпрджрд┐ рдЗрд╕ рд╕реНрдерд╛рди рдореЗрдВ рдкреНрд░рджрд░реНрд╢рди рдЖрдкрдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдорд╣рддреНрд╡рдкреВрд░реНрдг рдирд╣реАрдВ рд╣реИ, рддреЛ рд╕рдВрднрд╡рддрдГ рджреВрд╕рд░реЗ, рд╕рд░рд▓реАрдХреГрдд рд╕рдВрд╕реНрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЕрдзрд┐рдХ рд╕рд╣реА рд╣реИред рдлрд┐рд░ рднреА, рд╣рдо рдЬреЛ рднреА рдХреЛрдб рд▓рд┐рдЦрддреЗ рд╣реИрдВ, рдЙрд╕рдХрд╛ рдЕрдзрд┐рдХрд╛рдВрд╢ рднрд╛рдЧ рд╣рдорд╛рд░реЗ рдХрд╛рдорд░реЗрдб рдХреЗ рд▓рд┐рдП рд╣реЛрддрд╛ рд╣реИ, рдорд╢реАрдиреЛрдВ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВред

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


All Articles