View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.lang3;
19  
20  import java.util.Random;
21  import java.util.concurrent.TimeUnit;
22  
23  import org.openjdk.jmh.annotations.Benchmark;
24  import org.openjdk.jmh.annotations.BenchmarkMode;
25  import org.openjdk.jmh.annotations.Fork;
26  import org.openjdk.jmh.annotations.Measurement;
27  import org.openjdk.jmh.annotations.Mode;
28  import org.openjdk.jmh.annotations.OutputTimeUnit;
29  import org.openjdk.jmh.annotations.Param;
30  import org.openjdk.jmh.annotations.Scope;
31  import org.openjdk.jmh.annotations.Setup;
32  import org.openjdk.jmh.annotations.State;
33  import org.openjdk.jmh.annotations.Warmup;
34  
35  /**
36   * <p>
37   * JMH benchmark results for {@code StringUtils.join} on Java 21, executed without JaCoCo instrumentation.
38   * </p>
39   * <pre>
40   * mvn clean test -P benchmark -Dbenchmark=org.apache.commons.lang3.StringUtilsJoinBenchmark -P '!jacoco'
41   * </pre>
42   *
43   * <pre>
44   * Benchmark                                                              (size)  Mode  Cnt       Score       Error  Units
45   * StringUtilsJoinBenchmark.BooleanArrayBenchmark.testJoinBoolean_3_20_0      10  avgt    5      20.744 ±     0.254  ns/op
46   * StringUtilsJoinBenchmark.BooleanArrayBenchmark.testJoinBoolean_3_20_0     100  avgt    5      63.396 ±     0.933  ns/op
47   * StringUtilsJoinBenchmark.BooleanArrayBenchmark.testJoinBoolean_3_20_0    1000  avgt    5     245.837 ±    96.959  ns/op
48   * StringUtilsJoinBenchmark.BooleanArrayBenchmark.testJoinBoolean_3_20_0   10000  avgt    5     391.794 ±     1.479  ns/op
49   * StringUtilsJoinBenchmark.BooleanArrayBenchmark.testJoinBoolean_3_21_0      10  avgt    5      53.083 ±    10.429  ns/op
50   * StringUtilsJoinBenchmark.BooleanArrayBenchmark.testJoinBoolean_3_21_0     100  avgt    5      49.502 ±     3.611  ns/op
51   * StringUtilsJoinBenchmark.BooleanArrayBenchmark.testJoinBoolean_3_21_0    1000  avgt    5      52.685 ±    12.080  ns/op
52   * StringUtilsJoinBenchmark.BooleanArrayBenchmark.testJoinBoolean_3_21_0   10000  avgt    5      52.111 ±     8.522  ns/op
53   *
54   * StringUtilsJoinBenchmark.ByteArrayBenchmark.testJoinByte_3_20_0            10  avgt    5     111.913 ±    34.777  ns/op
55   * StringUtilsJoinBenchmark.ByteArrayBenchmark.testJoinByte_3_20_0           100  avgt    5     227.867 ±     1.022  ns/op
56   * StringUtilsJoinBenchmark.ByteArrayBenchmark.testJoinByte_3_20_0          1000  avgt    5    2512.815 ±     7.439  ns/op
57   * StringUtilsJoinBenchmark.ByteArrayBenchmark.testJoinByte_3_20_0         10000  avgt    5   24995.528 ±   371.981  ns/op
58   * StringUtilsJoinBenchmark.ByteArrayBenchmark.testJoinByte_3_21_0            10  avgt    5      39.934 ±    17.696  ns/op
59   * StringUtilsJoinBenchmark.ByteArrayBenchmark.testJoinByte_3_21_0           100  avgt    5     208.709 ±     0.630  ns/op
60   * StringUtilsJoinBenchmark.ByteArrayBenchmark.testJoinByte_3_21_0          1000  avgt    5    2028.011 ±    15.023  ns/op
61   * StringUtilsJoinBenchmark.ByteArrayBenchmark.testJoinByte_3_21_0         10000  avgt    5   20696.625 ±   334.290  ns/op
62   *
63   * StringUtilsJoinBenchmark.CharArrayBenchmark.testJoinChar_3_20_0            10  avgt    5      27.610 ±     1.302  ns/op
64   * StringUtilsJoinBenchmark.CharArrayBenchmark.testJoinChar_3_20_0           100  avgt    5     180.165 ±     3.730  ns/op
65   * StringUtilsJoinBenchmark.CharArrayBenchmark.testJoinChar_3_20_0          1000  avgt    5    1464.739 ±    41.632  ns/op
66   * StringUtilsJoinBenchmark.CharArrayBenchmark.testJoinChar_3_20_0         10000  avgt    5   13706.722 ±   208.715  ns/op
67   * StringUtilsJoinBenchmark.CharArrayBenchmark.testJoinChar_3_21_0            10  avgt    5      24.202 ±     3.130  ns/op
68   * StringUtilsJoinBenchmark.CharArrayBenchmark.testJoinChar_3_21_0           100  avgt    5     150.218 ±     2.129  ns/op
69   * StringUtilsJoinBenchmark.CharArrayBenchmark.testJoinChar_3_21_0          1000  avgt    5    1357.945 ±     8.898  ns/op
70   * StringUtilsJoinBenchmark.CharArrayBenchmark.testJoinChar_3_21_0         10000  avgt    5   13152.872 ±   447.029  ns/op
71   *
72   * StringUtilsJoinBenchmark.DoubleArrayBenchmark.testJoinDouble_3_20_0        10  avgt    5     327.488 ±     3.735  ns/op
73   * StringUtilsJoinBenchmark.DoubleArrayBenchmark.testJoinDouble_3_20_0       100  avgt    5    3246.046 ±    24.045  ns/op
74   * StringUtilsJoinBenchmark.DoubleArrayBenchmark.testJoinDouble_3_20_0      1000  avgt    5   33334.269 ±  1910.838  ns/op
75   * StringUtilsJoinBenchmark.DoubleArrayBenchmark.testJoinDouble_3_20_0     10000  avgt    5  330373.734 ± 10610.857  ns/op
76   * StringUtilsJoinBenchmark.DoubleArrayBenchmark.testJoinDouble_3_21_0        10  avgt    5     338.655 ±    15.557  ns/op
77   * StringUtilsJoinBenchmark.DoubleArrayBenchmark.testJoinDouble_3_21_0       100  avgt    5    3141.778 ±    65.095  ns/op
78   * StringUtilsJoinBenchmark.DoubleArrayBenchmark.testJoinDouble_3_21_0      1000  avgt    5   31349.168 ±   194.029  ns/op
79   * StringUtilsJoinBenchmark.DoubleArrayBenchmark.testJoinDouble_3_21_0     10000  avgt    5  315213.960 ± 26935.888  ns/op
80   *
81   * StringUtilsJoinBenchmark.FloatArrayBenchmark.testJoinFloat_3_20_0          10  avgt    5     224.880 ±     5.634  ns/op
82   * StringUtilsJoinBenchmark.FloatArrayBenchmark.testJoinFloat_3_20_0         100  avgt    5    2451.727 ±    22.667  ns/op
83   * StringUtilsJoinBenchmark.FloatArrayBenchmark.testJoinFloat_3_20_0        1000  avgt    5   31433.944 ±  2287.593  ns/op
84   * StringUtilsJoinBenchmark.FloatArrayBenchmark.testJoinFloat_3_20_0       10000  avgt    5  374632.760 ± 50931.471  ns/op
85   * StringUtilsJoinBenchmark.FloatArrayBenchmark.testJoinFloat_3_21_0          10  avgt    5     254.568 ±     9.830  ns/op
86   * StringUtilsJoinBenchmark.FloatArrayBenchmark.testJoinFloat_3_21_0         100  avgt    5    2916.277 ±   105.372  ns/op
87   * StringUtilsJoinBenchmark.FloatArrayBenchmark.testJoinFloat_3_21_0        1000  avgt    5   35840.570 ±  2000.700  ns/op
88   * StringUtilsJoinBenchmark.FloatArrayBenchmark.testJoinFloat_3_21_0       10000  avgt    5  293352.232 ± 20630.992  ns/op
89   *
90   * StringUtilsJoinBenchmark.IntArrayBenchmark.testJoinInt_3_20_0              10  avgt    5      84.855 ±     2.455  ns/op
91   * StringUtilsJoinBenchmark.IntArrayBenchmark.testJoinInt_3_20_0             100  avgt    5     796.464 ±    13.394  ns/op
92   * StringUtilsJoinBenchmark.IntArrayBenchmark.testJoinInt_3_20_0            1000  avgt    5    9734.390 ±   407.508  ns/op
93   * StringUtilsJoinBenchmark.IntArrayBenchmark.testJoinInt_3_20_0           10000  avgt    5   98763.469 ± 11627.264  ns/op
94   * StringUtilsJoinBenchmark.IntArrayBenchmark.testJoinInt_3_21_0              10  avgt    5      74.442 ±     0.558  ns/op
95   * StringUtilsJoinBenchmark.IntArrayBenchmark.testJoinInt_3_21_0             100  avgt    5     754.152 ±     2.570  ns/op
96   * StringUtilsJoinBenchmark.IntArrayBenchmark.testJoinInt_3_21_0            1000  avgt    5    7786.939 ±   105.617  ns/op
97   * StringUtilsJoinBenchmark.IntArrayBenchmark.testJoinInt_3_21_0           10000  avgt    5   78220.569 ±  2943.719  ns/op
98   *
99   * StringUtilsJoinBenchmark.LongArrayBenchmark.testJoinLong_3_20_0            10  avgt    5     160.601 ±     0.316  ns/op
100  * StringUtilsJoinBenchmark.LongArrayBenchmark.testJoinLong_3_20_0           100  avgt    5    1458.751 ±    34.769  ns/op
101  * StringUtilsJoinBenchmark.LongArrayBenchmark.testJoinLong_3_20_0          1000  avgt    5   15690.854 ±   203.858  ns/op
102  * StringUtilsJoinBenchmark.LongArrayBenchmark.testJoinLong_3_20_0         10000  avgt    5  158644.000 ±  1108.395  ns/op
103  * StringUtilsJoinBenchmark.LongArrayBenchmark.testJoinLong_3_21_0            10  avgt    5     150.858 ±     2.435  ns/op
104  * StringUtilsJoinBenchmark.LongArrayBenchmark.testJoinLong_3_21_0           100  avgt    5    1375.840 ±    14.656  ns/op
105  * StringUtilsJoinBenchmark.LongArrayBenchmark.testJoinLong_3_21_0          1000  avgt    5   14564.621 ±   278.250  ns/op
106  * StringUtilsJoinBenchmark.LongArrayBenchmark.testJoinLong_3_21_0         10000  avgt    5  152825.668 ±   877.466  ns/op
107  *
108  * StringUtilsJoinBenchmark.ShortArrayBenchmark.testJoinShort_3_20_0          10  avgt    5      45.996 ±     4.032  ns/op
109  * StringUtilsJoinBenchmark.ShortArrayBenchmark.testJoinShort_3_20_0         100  avgt    5     421.166 ±    10.521  ns/op
110  * StringUtilsJoinBenchmark.ShortArrayBenchmark.testJoinShort_3_20_0        1000  avgt    5    5396.685 ±    22.345  ns/op
111  * StringUtilsJoinBenchmark.ShortArrayBenchmark.testJoinShort_3_20_0       10000  avgt    5   59389.744 ±   795.609  ns/op
112  * StringUtilsJoinBenchmark.ShortArrayBenchmark.testJoinShort_3_21_0          10  avgt    5      51.526 ±     8.371  ns/op
113  * StringUtilsJoinBenchmark.ShortArrayBenchmark.testJoinShort_3_21_0         100  avgt    5     392.907 ±    30.972  ns/op
114  * StringUtilsJoinBenchmark.ShortArrayBenchmark.testJoinShort_3_21_0        1000  avgt    5    4869.440 ±    57.132  ns/op
115  * StringUtilsJoinBenchmark.ShortArrayBenchmark.testJoinShort_3_21_0       10000  avgt    5   51744.074 ±   121.176  ns/op
116  * </pre>
117  */
118 public class StringUtilsJoinBenchmark {
119 
120     @BenchmarkMode(Mode.AverageTime)
121     @OutputTimeUnit(TimeUnit.NANOSECONDS)
122     @State(Scope.Thread)
123     @Fork(1)
124     @Warmup(iterations = WARMUP_ITERATIONS, time = WARMUP_TIME)
125     @Measurement(iterations = MEASUREMENT_ITERATIONS, time = MEASUREMENT_TIME)
126     public static class BooleanArrayBenchmark {
127 
128         @Param({ "10", "100", "1000", "10000" })
129         private int size;
130         private boolean[] array;
131 
132         @Setup
133         public void setup() {
134             array = new boolean[size];
135             for (int i = 0; i < array.length; i++) {
136                 array[i] = i % 2 == 0;
137             }
138         }
139 
140         @Benchmark
141         public String testJoinBoolean_3_20_0() {
142             return StringUtils_3_20_0.join(array, ',', 0, 10);
143         }
144 
145         @Benchmark
146         public String testJoinBoolean_3_21_0() {
147             return StringUtils_3_21_0.join(array, ',', 0, 10);
148         }
149     }
150     @BenchmarkMode(Mode.AverageTime)
151     @OutputTimeUnit(TimeUnit.NANOSECONDS)
152     @State(Scope.Thread)
153     @Fork(1)
154     @Warmup(iterations = WARMUP_ITERATIONS, time = WARMUP_TIME)
155     @Measurement(iterations = MEASUREMENT_ITERATIONS, time = MEASUREMENT_TIME)
156     public static class ByteArrayBenchmark {
157 
158         @Param({ "10", "100", "1000", "10000" })
159         private int size;
160         private byte[] array;
161 
162         @Setup
163         public void setup() {
164             array = new byte[size];
165             final Random random = newRandom();
166             for (int i = 0; i < size; i++) {
167                 array[i] = (byte) random.nextInt(Byte.MAX_VALUE);
168             }
169         }
170 
171         @Benchmark
172         public String testJoinByte_3_20_0() {
173             return StringUtils_3_20_0.join(array, ',', 0, array.length);
174         }
175 
176         @Benchmark
177         public String testJoinByte_3_21_0() {
178             return StringUtils_3_21_0.join(array, ',', 0, array.length);
179         }
180     }
181     @BenchmarkMode(Mode.AverageTime)
182     @OutputTimeUnit(TimeUnit.NANOSECONDS)
183     @State(Scope.Thread)
184     @Fork(1)
185     @Warmup(iterations = WARMUP_ITERATIONS, time = WARMUP_TIME)
186     @Measurement(iterations = MEASUREMENT_ITERATIONS, time = MEASUREMENT_TIME)
187     public static class CharArrayBenchmark {
188 
189         @Param({ "10", "100", "1000", "10000" })
190         private int size;
191         private char[] array;
192 
193         @Setup
194         public void setup() {
195             array = new char[size];
196             final Random random = newRandom();
197             for (int i = 0; i < size; i++) {
198                 array[i] = (char) random.nextInt(Character.MAX_VALUE);
199             }
200         }
201 
202         @Benchmark
203         public String testJoinChar_3_20_0() {
204             return StringUtils_3_20_0.join(array, ',', 0, array.length);
205         }
206 
207         @Benchmark
208         public String testJoinChar_3_21_0() {
209             return StringUtils_3_21_0.join(array, ',', 0, array.length);
210         }
211     }
212     @BenchmarkMode(Mode.AverageTime)
213     @OutputTimeUnit(TimeUnit.NANOSECONDS)
214     @State(Scope.Thread)
215     @Fork(1)
216     @Warmup(iterations = WARMUP_ITERATIONS, time = WARMUP_TIME)
217     @Measurement(iterations = MEASUREMENT_ITERATIONS, time = MEASUREMENT_TIME)
218     public static class DoubleArrayBenchmark {
219 
220         @Param({ "10", "100", "1000", "10000" })
221         private int size;
222         private double[] array;
223 
224         @Setup
225         public void setup() {
226             array = new double[size];
227             final Random random = newRandom();
228             for (int i = 0; i < size; i++) {
229                 array[i] = random.nextDouble();
230             }
231         }
232 
233         @Benchmark
234         public String testJoinDouble_3_20_0() {
235             return StringUtils_3_20_0.join(array, ',', 0, array.length);
236         }
237 
238         @Benchmark
239         public String testJoinDouble_3_21_0() {
240             return StringUtils_3_21_0.join(array, ',', 0, array.length);
241         }
242     }
243 
244     @BenchmarkMode(Mode.AverageTime)
245     @OutputTimeUnit(TimeUnit.NANOSECONDS)
246     @State(Scope.Thread)
247     @Fork(1)
248     @Warmup(iterations = WARMUP_ITERATIONS, time = WARMUP_TIME)
249     @Measurement(iterations = MEASUREMENT_ITERATIONS, time = MEASUREMENT_TIME)
250     public static class FloatArrayBenchmark {
251 
252         @Param({ "10", "100", "1000", "10000" })
253         private int size;
254         private float[] array;
255 
256         @Setup
257         public void setup() {
258             array = new float[size];
259             final Random random = newRandom();
260             for (int i = 0; i < size; i++) {
261                 array[i] = random.nextFloat();
262             }
263         }
264 
265         @Benchmark
266         public String testJoinFloat_3_21_0() {
267             return StringUtils_3_21_0.join(array, ',', 0, array.length);
268         }
269 
270         @Benchmark
271         public String testJoinFloat3_20_0() {
272             return StringUtils_3_20_0.join(array, ',', 0, array.length);
273         }
274     }
275 
276     @BenchmarkMode(Mode.AverageTime)
277     @OutputTimeUnit(TimeUnit.NANOSECONDS)
278     @State(Scope.Thread)
279     @Fork(1)
280     @Warmup(iterations = WARMUP_ITERATIONS, time = WARMUP_TIME)
281     @Measurement(iterations = MEASUREMENT_ITERATIONS, time = MEASUREMENT_TIME)
282     public static class IntArrayBenchmark {
283 
284         @Param({ "10", "100", "1000", "10000" })
285         private int size;
286         private int[] array;
287 
288         @Setup
289         public void setup() {
290             array = new int[size];
291             final Random random = newRandom();
292             for (int i = 0; i < size; i++) {
293                 array[i] = random.nextInt();
294             }
295         }
296 
297         @Benchmark
298         public String testJoinInt_3_20_0() {
299             return StringUtils_3_20_0.join(array, ',', 0, array.length);
300         }
301 
302         @Benchmark
303         public String testJoinInt_3_21_0() {
304             return StringUtils_3_21_0.join(array, ',', 0, array.length);
305         }
306     }
307 
308     @BenchmarkMode(Mode.AverageTime)
309     @OutputTimeUnit(TimeUnit.NANOSECONDS)
310     @State(Scope.Thread)
311     @Fork(1)
312     @Warmup(iterations = WARMUP_ITERATIONS, time = WARMUP_TIME)
313     @Measurement(iterations = MEASUREMENT_ITERATIONS, time = MEASUREMENT_TIME)
314     public static class LongArrayBenchmark {
315 
316         @Param({ "10", "100", "1000", "10000" })
317         private int size;
318         private long[] array;
319 
320         @Setup
321         public void setup() {
322             array = new long[size];
323             final Random random = newRandom();
324             for (int i = 0; i < size; i++) {
325                 array[i] = random.nextLong();
326             }
327         }
328 
329         @Benchmark
330         public String testJoinLong_3_20_0() {
331             return StringUtils_3_20_0.join(array, ',', 0, array.length);
332         }
333 
334         @Benchmark
335         public String testJoinLong_3_21_0() {
336             return StringUtils_3_21_0.join(array, ',', 0, array.length);
337         }
338     }
339 
340     @BenchmarkMode(Mode.AverageTime)
341     @OutputTimeUnit(TimeUnit.NANOSECONDS)
342     @State(Scope.Thread)
343     @Fork(1)
344     @Warmup(iterations = WARMUP_ITERATIONS, time = WARMUP_TIME)
345     @Measurement(iterations = MEASUREMENT_ITERATIONS, time = MEASUREMENT_TIME)
346     public static class ShortArrayBenchmark {
347 
348         @Param({ "10", "100", "1000", "10000" })
349         private int size;
350         private short[] array;
351 
352         @Setup
353         public void setup() {
354             array = new short[size];
355             final Random random = newRandom();
356             for (int i = 0; i < size; i++) {
357                 array[i] = (short) random.nextInt(Short.MAX_VALUE);
358             }
359         }
360 
361         @Benchmark
362         public String testJoinShort_3_20_0() {
363             return StringUtils_3_20_0.join(array, ',', 0, array.length);
364         }
365 
366         @Benchmark
367         public String testJoinShort_3_21_0() {
368             return StringUtils_3_21_0.join(array, ',', 0, array.length);
369         }
370     }
371 
372     public static class StringUtils_3_20_0 {
373 
374         public static final String EMPTY = "";
375 
376         public static String join(final boolean[] array, final char delimiter, final int startIndex, final int endIndex) {
377             if (array == null) {
378                 return null;
379             }
380             if (endIndex - startIndex <= 0) {
381                 return EMPTY;
382             }
383             final StringBuilder stringBuilder = new StringBuilder(array.length * 5 + array.length - 1);
384             for (int i = startIndex; i < endIndex; i++) {
385                 stringBuilder.append(array[i]).append(delimiter);
386             }
387             return stringBuilder.substring(0, stringBuilder.length() - 1);
388         }
389 
390         public static String join(final byte[] array, final char delimiter, final int startIndex, final int endIndex) {
391             if (array == null) {
392                 return null;
393             }
394             if (endIndex - startIndex <= 0) {
395                 return EMPTY;
396             }
397             final StringBuilder stringBuilder = new StringBuilder();
398             for (int i = startIndex; i < endIndex; i++) {
399                 stringBuilder.append(array[i]).append(delimiter);
400             }
401             return stringBuilder.substring(0, stringBuilder.length() - 1);
402         }
403 
404         public static String join(final char[] array, final char delimiter, final int startIndex, final int endIndex) {
405             if (array == null) {
406                 return null;
407             }
408             if (endIndex - startIndex <= 0) {
409                 return EMPTY;
410             }
411             final StringBuilder stringBuilder = new StringBuilder(array.length * 2 - 1);
412             for (int i = startIndex; i < endIndex; i++) {
413                 stringBuilder.append(array[i]).append(delimiter);
414             }
415             return stringBuilder.substring(0, stringBuilder.length() - 1);
416         }
417 
418         public static String join(final double[] array, final char delimiter, final int startIndex, final int endIndex) {
419             if (array == null) {
420                 return null;
421             }
422             if (endIndex - startIndex <= 0) {
423                 return EMPTY;
424             }
425             final StringBuilder stringBuilder = new StringBuilder();
426             for (int i = startIndex; i < endIndex; i++) {
427                 stringBuilder.append(array[i]).append(delimiter);
428             }
429             return stringBuilder.substring(0, stringBuilder.length() - 1);
430         }
431 
432         public static String join(final float[] array, final char delimiter, final int startIndex, final int endIndex) {
433             if (array == null) {
434                 return null;
435             }
436             if (endIndex - startIndex <= 0) {
437                 return EMPTY;
438             }
439             final StringBuilder stringBuilder = new StringBuilder();
440             for (int i = startIndex; i < endIndex; i++) {
441                 stringBuilder.append(array[i]).append(delimiter);
442             }
443             return stringBuilder.substring(0, stringBuilder.length() - 1);
444         }
445 
446         public static String join(final int[] array, final char delimiter, final int startIndex, final int endIndex) {
447             if (array == null) {
448                 return null;
449             }
450             if (endIndex - startIndex <= 0) {
451                 return EMPTY;
452             }
453             final StringBuilder stringBuilder = new StringBuilder();
454             for (int i = startIndex; i < endIndex; i++) {
455                 stringBuilder.append(array[i]).append(delimiter);
456             }
457             return stringBuilder.substring(0, stringBuilder.length() - 1);
458         }
459 
460         public static String join(final long[] array, final char delimiter, final int startIndex, final int endIndex) {
461             if (array == null) {
462                 return null;
463             }
464             if (endIndex - startIndex <= 0) {
465                 return EMPTY;
466             }
467             final StringBuilder stringBuilder = new StringBuilder();
468             for (int i = startIndex; i < endIndex; i++) {
469                 stringBuilder.append(array[i]).append(delimiter);
470             }
471             return stringBuilder.substring(0, stringBuilder.length() - 1);
472         }
473 
474         public static String join(final short[] array, final char delimiter, final int startIndex, final int endIndex) {
475             if (array == null) {
476                 return null;
477             }
478             if (endIndex - startIndex <= 0) {
479                 return EMPTY;
480             }
481             final StringBuilder stringBuilder = new StringBuilder();
482             for (int i = startIndex; i < endIndex; i++) {
483                 stringBuilder.append(array[i]).append(delimiter);
484             }
485             return stringBuilder.substring(0, stringBuilder.length() - 1);
486         }
487     }
488 
489     public static class StringUtils_3_21_0 {
490 
491         public static final String EMPTY = "";
492 
493         private static StringBuilder capacity(final int count, final byte maxElementChars) {
494             return new StringBuilder(count * maxElementChars + count - 1);
495         }
496 
497         public static String join(final boolean[] array, final char delimiter, final int startIndex, final int endIndex) {
498             if (array == null) {
499                 return null;
500             }
501             final int count = endIndex - startIndex;
502             if (count <= 0) {
503                 return EMPTY;
504             }
505             final byte maxElementChars = 5; // "false".length()
506             final StringBuilder stringBuilder = capacity(count, maxElementChars);
507             stringBuilder.append(array[startIndex]);
508             for (int i = startIndex + 1; i < endIndex; i++) {
509                 stringBuilder.append(delimiter).append(array[i]);
510             }
511             return stringBuilder.toString();
512         }
513 
514         public static String join(final byte[] array, final char delimiter, final int startIndex, final int endIndex) {
515             if (array == null) {
516                 return null;
517             }
518             final int count = endIndex - startIndex;
519             if (count <= 0) {
520                 return EMPTY;
521             }
522             final byte maxElementChars = 4; // "-128"
523             final StringBuilder stringBuilder = capacity(count, maxElementChars);
524             stringBuilder.append(array[startIndex]);
525             for (int i = startIndex + 1; i < endIndex; i++) {
526                 stringBuilder.append(delimiter).append(array[i]);
527             }
528             return stringBuilder.toString();
529         }
530 
531         public static String join(final char[] array, final char delimiter, final int startIndex, final int endIndex) {
532             if (array == null) {
533                 return null;
534             }
535             final int count = endIndex - startIndex;
536             if (count <= 0) {
537                 return EMPTY;
538             }
539             final byte maxElementChars = 1;
540             final StringBuilder stringBuilder = capacity(count, maxElementChars);
541             stringBuilder.append(array[startIndex]);
542             for (int i = startIndex + 1; i < endIndex; i++) {
543                 stringBuilder.append(delimiter).append(array[i]);
544             }
545             return stringBuilder.toString();
546         }
547 
548         public static String join(final double[] array, final char delimiter, final int startIndex, final int endIndex) {
549             if (array == null) {
550                 return null;
551             }
552             final int count = endIndex - startIndex;
553             if (count <= 0) {
554                 return EMPTY;
555             }
556             final byte maxElementChars = 22; // "1.7976931348623157E308"
557             final StringBuilder stringBuilder = capacity(count, maxElementChars);
558             stringBuilder.append(array[startIndex]);
559             for (int i = startIndex + 1; i < endIndex; i++) {
560                 stringBuilder.append(delimiter).append(array[i]);
561             }
562             return stringBuilder.toString();
563         }
564 
565         public static String join(final float[] array, final char delimiter, final int startIndex, final int endIndex) {
566             if (array == null) {
567                 return null;
568             }
569             final int count = endIndex - startIndex;
570             if (count <= 0) {
571                 return EMPTY;
572             }
573             final byte maxElementChars = 12; // "3.4028235E38"
574             final StringBuilder stringBuilder = capacity(count, maxElementChars);
575             stringBuilder.append(array[startIndex]);
576             for (int i = startIndex + 1; i < endIndex; i++) {
577                 stringBuilder.append(delimiter).append(array[i]);
578             }
579             return stringBuilder.toString();
580         }
581 
582         public static String join(final int[] array, final char delimiter, final int startIndex, final int endIndex) {
583             if (array == null) {
584                 return null;
585             }
586             final int count = endIndex - startIndex;
587             if (count <= 0) {
588                 return EMPTY;
589             }
590             final byte maxElementChars = 11; // "-2147483648"
591             final StringBuilder stringBuilder = capacity(count, maxElementChars);
592             stringBuilder.append(array[startIndex]);
593             for (int i = startIndex + 1; i < endIndex; i++) {
594                 stringBuilder.append(delimiter).append(array[i]);
595             }
596             return stringBuilder.toString();
597         }
598 
599         public static String join(final long[] array, final char delimiter, final int startIndex, final int endIndex) {
600             if (array == null) {
601                 return null;
602             }
603             final int count = endIndex - startIndex;
604             if (count <= 0) {
605                 return EMPTY;
606             }
607             final byte maxElementChars = 20; // "-9223372036854775808"
608             final StringBuilder stringBuilder = capacity(count, maxElementChars);
609             stringBuilder.append(array[startIndex]);
610             for (int i = startIndex + 1; i < endIndex; i++) {
611                 stringBuilder.append(delimiter).append(array[i]);
612             }
613             return stringBuilder.toString();
614         }
615 
616         public static String join(final short[] array, final char delimiter, final int startIndex, final int endIndex) {
617             if (array == null) {
618                 return null;
619             }
620             final int count = endIndex - startIndex;
621             if (count <= 0) {
622                 return EMPTY;
623             }
624             final byte maxElementChars = 6; // "-32768"
625             final StringBuilder stringBuilder = capacity(count, maxElementChars);
626             stringBuilder.append(array[startIndex]);
627             for (int i = startIndex + 1; i < endIndex; i++) {
628                 stringBuilder.append(delimiter).append(array[i]);
629             }
630             return stringBuilder.toString();
631         }
632     }
633 
634     private static final int WARMUP_ITERATIONS = 3;
635 
636     private static final int WARMUP_TIME = 1;
637 
638     private static final int MEASUREMENT_ITERATIONS = 5;
639 
640     private static final int MEASUREMENT_TIME = 1;
641 
642     private static Random newRandom() {
643         return new Random(235);
644     }
645 }