1/* 2 * Copyright (C) 2011 Google Inc. 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 17package benchmarks.regression; 18 19import com.google.caliper.Param; 20import java.util.Locale; 21 22public class StringCaseMappingBenchmark { 23 enum Inputs { 24 EMPTY(""), 25 26 // TODO: include hairy inputs like turkish and greek. 27 // TODO: locale makes a difference too. 28 29 LOWER2(lower(2)), 30 UPPER2(upper(2)), 31 MIXED2(mixed(2)), 32 33 LOWER8(lower(8)), 34 UPPER8(upper(8)), 35 MIXED8(mixed(8)), 36 37 LOWER32(lower(32)), 38 UPPER32(upper(32)), 39 MIXED32(mixed(32)), 40 41 LOWER512(lower(512)), 42 UPPER512(upper(512)), 43 MIXED512(mixed(512)), 44 45 LOWER2048(lower(2048)), 46 UPPER2048(upper(2048)), 47 MIXED2048(mixed(2048)), 48 49 LOWER_1M(lower(1024*1024)), 50 UPPER_1M(upper(1024*1024)), 51 MIXED_1M(mixed(1024*1024)); 52 53 final String value; 54 private Inputs(String value) { this.value = value; } 55 private static String lower(int length) { 56 return makeString(length, "a0b1c2d3e4f5g6h7i8j9klmnopqrstuvwxyz"); 57 } 58 private static String upper(int length) { 59 return makeString(length, "A0B1C2D3E4F5G6H7I8J9KLMNOPQRSTUVWXYZ"); 60 } 61 private static String mixed(int length) { 62 return makeString(length, "Aa0Bb1Cc2Dd3Ee4Ff5Gg6Hh7Ii8Jj9KkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"); 63 } 64 private static String makeString(int length, String alphabet) { 65 StringBuilder sb = new StringBuilder(length); 66 for (int i = 0; i < length; ++i) { 67 sb.append(alphabet.charAt(i % alphabet.length())); 68 } 69 return sb.toString(); 70 } 71 } 72 @Param private Inputs s; 73 74 public void timeToUpperCase_US(int reps) { 75 for (int i = 0; i < reps; ++i) { 76 s.value.toUpperCase(Locale.US); 77 } 78 } 79 80 // toUpperCase for Greek is an extra-hard case that uses icu4c's Transliterator. 81 public void timeToUpperCase_el_GR(int reps) { 82 Locale el_GR = new Locale("el", "GR"); 83 for (int i = 0; i < reps; ++i) { 84 s.value.toUpperCase(el_GR); 85 } 86 } 87 88 public void timeToLowerCase_US(int reps) { 89 for (int i = 0; i < reps; ++i) { 90 s.value.toLowerCase(Locale.US); 91 } 92 } 93 94 public void timeToUpperCase_Ascii(int reps) { 95 for (int i = 0; i < reps; ++i) { 96 toUpperCaseAscii(s.value); 97 } 98 } 99 100 public void timeToLowerCase_Ascii(int reps) { 101 for (int i = 0; i < reps; ++i) { 102 toLowerCaseAscii(s.value); 103 } 104 } 105 106 public void timeToUpperCase_ICU(int reps) { 107 for (int i = 0; i < reps; ++i) { 108 libcore.icu.ICU.toUpperCase(s.value, Locale.US); 109 } 110 } 111 112 public void timeToLowerCase_ICU(int reps) { 113 for (int i = 0; i < reps; ++i) { 114 libcore.icu.ICU.toLowerCase(s.value, Locale.US); 115 } 116 } 117 118 public static String toUpperCaseAscii(String s) { 119 for (int i = 0, length = s.length(); i < length; i++) { 120 char c = s.charAt(i); 121 if (c < 'a' || c > 'z') { 122 continue; // fast path avoids allocation 123 } 124 125 // slow path: s contains lower case chars 126 char[] result = s.toCharArray(); 127 for (; i < length; i++) { 128 c = result[i]; 129 if (c >= 'a' && c <= 'z') { 130 result[i] -= ('a' - 'A'); 131 } 132 } 133 return new String(result); 134 } 135 return s; 136 } 137 138 public static String toLowerCaseAscii(String s) { 139 for (int i = 0, length = s.length(); i < length; i++) { 140 char c = s.charAt(i); 141 if (c < 'A' || c > 'Z') { 142 continue; // fast path avoids allocation 143 } 144 145 // slow path: s contains upper case chars 146 char[] result = s.toCharArray(); 147 for (; i < length; i++) { 148 c = result[i]; 149 if (c >= 'A' && c <= 'Z') { 150 result[i] += ('a' - 'A'); 151 } 152 } 153 return new String(result); 154 } 155 return s; 156 } 157} 158