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 23 /** 24 * Microbenchmark for {@link com.google.common.base.Strings#repeat} 25 * 26 * @author Mike Cripps 27 */ 28 public class StringsRepeatBenchmark { 29 @Param({"1", "5", "25", "125"}) 30 int count; 31 32 @Param({"1", "10"}) 33 int length; 34 35 private String originalString; 36 37 @BeforeExperiment setUp()38 void setUp() { 39 originalString = Strings.repeat("x", length); 40 } 41 42 @Benchmark oldRepeat(int reps)43 void oldRepeat(int reps) { 44 for (int i = 0; i < reps; i++) { 45 String x = oldRepeat(originalString, count); 46 if (x.length() != (originalString.length() * count)) { 47 throw new RuntimeException("Wrong length: " + x); 48 } 49 } 50 } 51 oldRepeat(String string, int count)52 private static String oldRepeat(String string, int count) { 53 // If this multiplication overflows, a NegativeArraySizeException or 54 // OutOfMemoryError is not far behind 55 final int len = string.length(); 56 final int size = len * count; 57 char[] array = new char[size]; 58 for (int i = 0; i < size; i += len) { 59 string.getChars(0, len, array, i); 60 } 61 return new String(array); 62 } 63 64 @Benchmark mikeRepeat(int reps)65 void mikeRepeat(int reps) { 66 for (int i = 0; i < reps; i++) { 67 String x = mikeRepeat(originalString, count); 68 if (x.length() != (originalString.length() * count)) { 69 throw new RuntimeException("Wrong length: " + x); 70 } 71 } 72 } 73 mikeRepeat(String string, int count)74 private static String mikeRepeat(String string, int count) { 75 final int len = string.length(); 76 char[] strCopy = new char[len * Integer.highestOneBit(count)]; 77 string.getChars(0, len, strCopy, 0); 78 79 char[] array = new char[len * count]; 80 81 int strCopyLen = len; 82 int pos = 0; 83 while (count != 0) { 84 if ((count & 1) != 0) { 85 System.arraycopy(strCopy, 0, array, pos, strCopyLen); 86 pos += strCopyLen; 87 } 88 count >>= 1; 89 if (count != 0) { 90 System.arraycopy(strCopy, 0, strCopy, strCopyLen, strCopyLen); 91 strCopyLen <<= 1; 92 } 93 } 94 return new String(array); 95 } 96 97 @Benchmark martinRepeat(int reps)98 void martinRepeat(int reps) { 99 for (int i = 0; i < reps; i++) { 100 String x = martinRepeat(originalString, count); 101 if (x.length() != (originalString.length() * count)) { 102 throw new RuntimeException("Wrong length: " + x); 103 } 104 } 105 } 106 martinRepeat(String string, int count)107 private static String martinRepeat(String string, int count) { 108 final int len = string.length(); 109 final int size = len * count; 110 final char[] array = new char[size]; 111 string.getChars(0, len, array, 0); 112 int n; 113 for (n = len; n < size - n; n <<= 1) { 114 System.arraycopy(array, 0, array, n, n); 115 } 116 System.arraycopy(array, 0, array, n, size - n); 117 return new String(array); 118 } 119 } 120