1 /*
2  * Copyright (C) 2011 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.base;
18 
19 import com.google.caliper.BeforeExperiment;
20 import com.google.caliper.Benchmark;
21 import com.google.caliper.Param;
22 import com.google.common.base.Strings;
23 
24 /**
25  * Microbenchmark for {@link Strings#repeat}
26  *
27  * @author Mike Cripps
28  */
29 public class StringsRepeatBenchmark {
30   @Param({"1", "5", "25", "125"}) int count;
31   @Param({"1", "10"}) int length;
32 
33   private String originalString;
34 
setUp()35   @BeforeExperiment void setUp() {
36     originalString = Strings.repeat("x", length);
37   }
38 
oldRepeat(int reps)39   @Benchmark void oldRepeat(int reps) {
40     for (int i = 0; i < reps; i++) {
41       String x = oldRepeat(originalString, count);
42       if (x.length() != (originalString.length() * count)) {
43         throw new RuntimeException("Wrong length: "+x);
44       }
45     }
46   }
mikeRepeat(int reps)47   @Benchmark void mikeRepeat(int reps) {
48     for (int i = 0; i < reps; i++) {
49       String x = mikeRepeat(originalString, count);
50       if (x.length() != (originalString.length() * count)) {
51         throw new RuntimeException("Wrong length: "+x);
52       }
53     }
54   }
martinRepeat(int reps)55   @Benchmark void martinRepeat(int reps) {
56     for (int i = 0; i < reps; i++) {
57       String x = martinRepeat(originalString, count);
58       if (x.length() != (originalString.length() * count)) {
59         throw new RuntimeException("Wrong length: "+x);
60       }
61     }
62   }
63 
mikeRepeat(String string, int count)64   private static String mikeRepeat(String string, int count) {
65     final int len = string.length();
66     char[] strCopy = new char[len * Integer.highestOneBit(count)];
67     string.getChars(0, len, strCopy, 0);
68 
69     char[] array = new char[len * count];
70 
71     int strCopyLen = len;
72     int pos = 0;
73     while (count != 0) {
74       if ((count & 1) != 0) {
75         System.arraycopy(strCopy, 0, array, pos,strCopyLen);
76         pos += strCopyLen;
77       }
78       count >>= 1;
79       if (count != 0) {
80         System.arraycopy(strCopy, 0, strCopy, strCopyLen, strCopyLen);
81         strCopyLen <<= 1;
82       }
83     }
84     return new String(array);
85   }
86 
oldRepeat(String string, int count)87   private static String oldRepeat(String string, int count) {
88     // If this multiplication overflows, a NegativeArraySizeException or
89     // OutOfMemoryError is not far behind
90     final int len = string.length();
91     final int size = len * count;
92     char[] array = new char[size];
93     for (int i = 0; i < size; i+=len) {
94       string.getChars(0, len, array, i);
95     }
96     return new String(array);
97   }
98 
martinRepeat(String string, int count)99   private static String martinRepeat(String string, int count) {
100     final int len = string.length();
101     final int size = len * count;
102     final char[] array = new char[size];
103     string.getChars(0, len, array, 0);
104     int n;
105     for (n = len; n < size - n; n <<= 1) {
106       System.arraycopy(array, 0, array, n, n);
107     }
108     System.arraycopy(array, 0, array, n, size - n);
109     return new String(array);
110   }
111 }
112