summaryrefslogtreecommitdiff
path: root/src/main/java/org/linaro/benchmarks/micro/StringOps.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/linaro/benchmarks/micro/StringOps.java')
-rw-r--r--src/main/java/org/linaro/benchmarks/micro/StringOps.java425
1 files changed, 425 insertions, 0 deletions
diff --git a/src/main/java/org/linaro/benchmarks/micro/StringOps.java b/src/main/java/org/linaro/benchmarks/micro/StringOps.java
new file mode 100644
index 0000000..5851c36
--- /dev/null
+++ b/src/main/java/org/linaro/benchmarks/micro/StringOps.java
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2016 Linaro Limited. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * Description: Tracks performance of String intrinsics, Java, and native methods.
+ * Main Focus: Looped memory compare.
+ * Secondary Focus: Array access.
+ *
+ */
+
+package org.linaro.benchmarks.micro;
+
+import java.lang.StringBuilder;
+import java.lang.System;
+import java.util.Random;
+import org.openjdk.jmh.annotations.*;
+import java.util.concurrent.TimeUnit;
+
+@BenchmarkMode(Mode.AverageTime)
+@OutputTimeUnit(TimeUnit.NANOSECONDS)
+@State(Scope.Benchmark)
+
+public class StringOps {
+
+ private static int RANDOM_STRING_8 = 0;
+ private static int RANDOM_STRING_16 = 1;
+ private static int RANDOM_STRING_32 = 2;
+ private static int RANDOM_STRING_128 = 3;
+ private static int RANDOM_STRING_512 = 4;
+ private static int NUM_LENGTH_TESTS = 5;
+
+ private static char MIN_RANDOM_CHAR = 65;
+ private static char MAX_RANDOM_CHAR = 123;
+ private static char searchChar;
+
+ /* Intentionally use the same seed each time for consistency across benchmark runs. */
+ private static int SAME_SEED = 0;
+
+ /* Random string data. */
+ private static Random rnd = new Random(SAME_SEED);
+ private static String[] stringData = new String[NUM_LENGTH_TESTS];
+
+ /* Same random string data as above for comparing different instances of the same char data. */
+ private static Random rndAlt = new Random(SAME_SEED);
+ private static String[] stringDataAlt = new String[NUM_LENGTH_TESTS];
+
+ /* Benchmark results cache for preventing DCE. */
+ private static boolean[] stringEqualsResults = new boolean[NUM_LENGTH_TESTS];
+ private static boolean[] stringEqualsIgnoreCaseResults = new boolean[NUM_LENGTH_TESTS];
+ private static boolean[] stringContentEqualsResults = new boolean[NUM_LENGTH_TESTS];
+ private static int[] stringCompareToResults = new int[NUM_LENGTH_TESTS];
+ private static int[] stringCompareToIgnoreCaseResults = new int[NUM_LENGTH_TESTS];
+ private static boolean[] stringRegionMatchesResults = new boolean[NUM_LENGTH_TESTS];
+ private static boolean[] stringRegionMatchesIgnoreCaseResults = new boolean[NUM_LENGTH_TESTS];
+ private static char stringCharAtResult;
+ private static int stringIndexOfResult;
+ private static int stringIndexOfAfterResult;
+ private static String[] stringNewStringFromBytesResult = new String[NUM_LENGTH_TESTS];
+ private static String[] stringNewStringFromCharsResult = new String[NUM_LENGTH_TESTS];
+ private static String[] stringNewStringFromStringResult = new String[NUM_LENGTH_TESTS];
+ private static String[] stringGetCharsNoCheckResult = new String[NUM_LENGTH_TESTS];
+
+ private static char []chars_8 = new char[8];
+ private static char []chars_16 = new char[16];
+ private static char []chars_32 = new char[32];
+ private static char []chars_128 = new char[128];
+ private static char []chars_512 = new char[512];
+
+ private static String generateRandomString(int len, Random rnd) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < len - 1; i++) {
+ /* Compose random string data from upper and lower case english alphabet entries plus a few
+ * harmless characters in-between. */
+ sb.append(Character.valueOf((char)(MIN_RANDOM_CHAR +
+ rnd.nextInt(MAX_RANDOM_CHAR - MIN_RANDOM_CHAR))));
+ }
+ sb.append(Character.valueOf(MAX_RANDOM_CHAR));
+ return sb.toString();
+ }
+
+ private static void generateRandomStrings(Random rnd, String[] output) {
+ output[RANDOM_STRING_8] = generateRandomString(8, rnd);
+ output[RANDOM_STRING_16] = generateRandomString(16, rnd);
+ output[RANDOM_STRING_32] = generateRandomString(32, rnd);
+ output[RANDOM_STRING_128] = generateRandomString(128, rnd);
+ output[RANDOM_STRING_512] = generateRandomString(512, rnd);
+ }
+
+ static {
+ searchChar = MAX_RANDOM_CHAR;
+ generateRandomStrings(rnd, stringData);
+ generateRandomStrings(rndAlt, stringDataAlt);
+ }
+
+ /**
+ * String.equals
+ */
+
+ @Benchmark
+ public void jmhTimeStringEqualsSmall() {
+ stringEqualsResults[RANDOM_STRING_8]
+ ^= stringData[RANDOM_STRING_8].equals(stringDataAlt[RANDOM_STRING_8]);
+ stringEqualsResults[RANDOM_STRING_16]
+ ^= stringData[RANDOM_STRING_16].equals(stringDataAlt[RANDOM_STRING_16]);
+ stringEqualsResults[RANDOM_STRING_32]
+ ^= stringData[RANDOM_STRING_32].equals(stringDataAlt[RANDOM_STRING_32]);
+ }
+
+ @Benchmark
+ public void jmhTimeStringEqualsLarge() {
+ stringEqualsResults[RANDOM_STRING_128]
+ ^= stringData[RANDOM_STRING_128].equals(stringDataAlt[RANDOM_STRING_128]);
+ stringEqualsResults[RANDOM_STRING_512]
+ ^= stringData[RANDOM_STRING_512].equals(stringDataAlt[RANDOM_STRING_512]);
+ }
+
+ /**
+ * String.equalsIgnoreCase
+ */
+
+ @Benchmark
+ public void jmhTimeStringEqualsIgnoreCaseSmall() {
+ stringEqualsIgnoreCaseResults[RANDOM_STRING_8]
+ ^= stringData[RANDOM_STRING_8].equalsIgnoreCase(
+ stringDataAlt[RANDOM_STRING_8]);
+ stringEqualsIgnoreCaseResults[RANDOM_STRING_16]
+ ^= stringData[RANDOM_STRING_16].equalsIgnoreCase(
+ stringDataAlt[RANDOM_STRING_16]);
+ stringEqualsIgnoreCaseResults[RANDOM_STRING_32]
+ ^= stringData[RANDOM_STRING_32].equalsIgnoreCase(
+ stringDataAlt[RANDOM_STRING_32]);
+ }
+
+ @Benchmark
+ public void jmhTimeStringEqualsIgnoreCaseLarge() {
+ stringEqualsIgnoreCaseResults[RANDOM_STRING_128]
+ ^= stringData[RANDOM_STRING_128].equalsIgnoreCase(
+ stringDataAlt[RANDOM_STRING_128]);
+ stringEqualsIgnoreCaseResults[RANDOM_STRING_512]
+ ^= stringData[RANDOM_STRING_512].equalsIgnoreCase(
+ stringDataAlt[RANDOM_STRING_512]);
+ }
+
+ /**
+ * String.contentEquals
+ */
+
+ @Benchmark
+ public void jmhTimeStringContentEqualsSmall() {
+ stringContentEqualsResults[RANDOM_STRING_8]
+ ^= stringData[RANDOM_STRING_8].contentEquals(
+ stringDataAlt[RANDOM_STRING_8]);
+ stringContentEqualsResults[RANDOM_STRING_16]
+ ^= stringData[RANDOM_STRING_16].contentEquals(
+ stringDataAlt[RANDOM_STRING_16]);
+ stringContentEqualsResults[RANDOM_STRING_32]
+ ^= stringData[RANDOM_STRING_32].contentEquals(
+ stringDataAlt[RANDOM_STRING_32]);
+ }
+
+ @Benchmark
+ public void jmhTimeStringContentEqualsLarge() {
+ stringContentEqualsResults[RANDOM_STRING_128]
+ ^= stringData[RANDOM_STRING_128].contentEquals(
+ stringDataAlt[RANDOM_STRING_128]);
+ stringContentEqualsResults[RANDOM_STRING_512]
+ ^= stringData[RANDOM_STRING_512].contentEquals(
+ stringDataAlt[RANDOM_STRING_512]);
+ }
+
+ /**
+ * String.compareTo
+ */
+
+ @Benchmark
+ public void jmhTimeStringCompareToSmall() {
+ stringCompareToResults[RANDOM_STRING_8]
+ += stringData[RANDOM_STRING_8].compareTo(stringDataAlt[RANDOM_STRING_8]);
+ stringCompareToResults[RANDOM_STRING_16]
+ += stringData[RANDOM_STRING_16].compareTo(stringDataAlt[RANDOM_STRING_16]);
+ stringCompareToResults[RANDOM_STRING_32]
+ += stringData[RANDOM_STRING_32].compareTo(stringDataAlt[RANDOM_STRING_32]);
+ }
+
+ @Benchmark
+ public void jmhTimeStringCompareToLarge() {
+ stringCompareToResults[RANDOM_STRING_128]
+ += stringData[RANDOM_STRING_128].compareTo(stringDataAlt[RANDOM_STRING_128]);
+ stringCompareToResults[RANDOM_STRING_512]
+ += stringData[RANDOM_STRING_512].compareTo(stringDataAlt[RANDOM_STRING_512]);
+ }
+
+ /**
+ * String.compareToIgnoreCase
+ */
+
+ @Benchmark
+ public void jmhTimeStringCompareToIgnoreCaseSmall() {
+ stringCompareToIgnoreCaseResults[RANDOM_STRING_8]
+ += stringData[RANDOM_STRING_8].compareToIgnoreCase(
+ stringDataAlt[RANDOM_STRING_8]);
+ stringCompareToIgnoreCaseResults[RANDOM_STRING_16]
+ += stringData[RANDOM_STRING_16].compareToIgnoreCase(
+ stringDataAlt[RANDOM_STRING_16]);
+ stringCompareToIgnoreCaseResults[RANDOM_STRING_32]
+ += stringData[RANDOM_STRING_32].compareToIgnoreCase(
+ stringDataAlt[RANDOM_STRING_32]);
+ }
+
+ @Benchmark
+ public void jmhTimeStringCompareToIgnoreCaseLarge() {
+ stringCompareToIgnoreCaseResults[RANDOM_STRING_128]
+ += stringData[RANDOM_STRING_128].compareToIgnoreCase(
+ stringDataAlt[RANDOM_STRING_128]);
+ stringCompareToIgnoreCaseResults[RANDOM_STRING_512]
+ += stringData[RANDOM_STRING_512].compareToIgnoreCase(
+ stringDataAlt[RANDOM_STRING_512]);
+ }
+
+ /**
+ * String.regionMatches
+ */
+
+ @Benchmark
+ public void jmhTimeStringRegionMatchesSmall() {
+ stringRegionMatchesResults[RANDOM_STRING_8]
+ ^= stringData[RANDOM_STRING_8].regionMatches(
+ 0, stringDataAlt[RANDOM_STRING_8], 0, 8);
+ stringRegionMatchesResults[RANDOM_STRING_16]
+ ^= stringData[RANDOM_STRING_16].regionMatches(
+ 0, stringDataAlt[RANDOM_STRING_16], 0, 16);
+ stringRegionMatchesResults[RANDOM_STRING_32]
+ ^= stringData[RANDOM_STRING_32].regionMatches(
+ 0, stringDataAlt[RANDOM_STRING_32], 0, 32);
+ }
+
+ @Benchmark
+ public void jmhTimeStringRegionMatchesLarge() {
+ stringRegionMatchesResults[RANDOM_STRING_128]
+ ^= stringData[RANDOM_STRING_128].regionMatches(
+ 0, stringDataAlt[RANDOM_STRING_128], 0, 128);
+ stringRegionMatchesResults[RANDOM_STRING_512]
+ ^= stringData[RANDOM_STRING_512].regionMatches(
+ 0, stringDataAlt[RANDOM_STRING_512], 0, 512);
+ }
+
+ /**
+ * String.regionMatches
+ */
+
+ @Benchmark
+ public void jmhTimeStringRegionMatchesIgnoreCaseSmall() {
+ stringRegionMatchesIgnoreCaseResults[RANDOM_STRING_8]
+ ^= stringData[RANDOM_STRING_8].regionMatches(
+ true, 0, stringDataAlt[RANDOM_STRING_8], 0, 8);
+ stringRegionMatchesIgnoreCaseResults[RANDOM_STRING_16]
+ ^= stringData[RANDOM_STRING_16].regionMatches(
+ true, 0, stringDataAlt[RANDOM_STRING_16], 0, 16);
+ stringRegionMatchesIgnoreCaseResults[RANDOM_STRING_32]
+ ^= stringData[RANDOM_STRING_32].regionMatches(
+ true, 0, stringDataAlt[RANDOM_STRING_32], 0, 32);
+ }
+
+ @Benchmark
+ public void jmhTimeStringRegionMatchesIgnoreCaseLarge() {
+ stringRegionMatchesIgnoreCaseResults[RANDOM_STRING_128]
+ ^= stringData[RANDOM_STRING_128].regionMatches(
+ true, 0, stringDataAlt[RANDOM_STRING_128], 0, 128);
+ stringRegionMatchesIgnoreCaseResults[RANDOM_STRING_512]
+ ^= stringData[RANDOM_STRING_512].regionMatches(
+ true, 0, stringDataAlt[RANDOM_STRING_512], 0, 512);
+ }
+
+ /**
+ * String.charAt
+ */
+
+ @Benchmark
+ public void jmhTimeStringCharAt() {
+ for (int j = 0; j < 512; j++) {
+ stringCharAtResult = stringData[RANDOM_STRING_512].charAt(j);
+ }
+ }
+
+ /**
+ * String.indexOf
+ */
+
+ @Benchmark
+ public void jmhTimeStringIndexOfSmall() {
+ stringIndexOfResult += stringData[RANDOM_STRING_8].indexOf(searchChar);
+ stringIndexOfResult += stringData[RANDOM_STRING_16].indexOf(searchChar);
+ stringIndexOfResult += stringData[RANDOM_STRING_32].indexOf(searchChar);
+ }
+
+ @Benchmark
+ public void jmhTimeStringIndexOfLarge() {
+ stringIndexOfResult += stringData[RANDOM_STRING_128].indexOf(searchChar);
+ stringIndexOfResult += stringData[RANDOM_STRING_512].indexOf(searchChar);
+ }
+
+ /**
+ * String.indexOfAfter
+ */
+
+ @Benchmark
+ public void jmhTimeStringIndexOfAfterSmall() {
+ stringIndexOfAfterResult += stringData[RANDOM_STRING_8].indexOf(searchChar, 1);
+ stringIndexOfAfterResult += stringData[RANDOM_STRING_16].indexOf(searchChar, 1);
+ stringIndexOfAfterResult += stringData[RANDOM_STRING_32].indexOf(searchChar, 1);
+ }
+
+ @Benchmark
+ public void jmhTimeStringIndexOfAfterLarge() {
+ stringIndexOfAfterResult += stringData[RANDOM_STRING_128].indexOf(searchChar, 1);
+ stringIndexOfAfterResult += stringData[RANDOM_STRING_512].indexOf(searchChar, 1);
+ }
+
+ /**
+ * NewStringFromBytes
+ */
+
+ @Benchmark
+ public void jmhTimeStringNewStringFromBytesSmall() {
+ byte[] bytes = stringData[RANDOM_STRING_8].getBytes();
+ stringNewStringFromBytesResult[RANDOM_STRING_8] = new String(bytes);
+ byte[] bytes2 = stringData[RANDOM_STRING_16].getBytes();
+ stringNewStringFromBytesResult[RANDOM_STRING_16] = new String(bytes2);
+ byte[] bytes3 = stringData[RANDOM_STRING_32].getBytes();
+ stringNewStringFromBytesResult[RANDOM_STRING_32] = new String(bytes3);
+ }
+
+ @Benchmark
+ public void jmhTimeStringNewStringFromBytesLarge() {
+ byte[] bytes = stringData[RANDOM_STRING_128].getBytes();
+ stringNewStringFromBytesResult[RANDOM_STRING_128] = new String(bytes);
+ byte[] bytes2 = stringData[RANDOM_STRING_512].getBytes();
+ stringNewStringFromBytesResult[RANDOM_STRING_512] = new String(bytes2);
+ }
+
+ /**
+ * NewStringFromChars
+ */
+
+ @Benchmark
+ public void jmhTimeStringNewStringFromCharsSmall() {
+ char[] chars = new char[8];
+ stringData[RANDOM_STRING_8].getChars(0, 8, chars, 0);
+ stringNewStringFromCharsResult[RANDOM_STRING_8] = new String(chars);
+ char[] chars2 = new char[16];
+ stringData[RANDOM_STRING_16].getChars(0, 16, chars2, 0);
+ stringNewStringFromCharsResult[RANDOM_STRING_16] = new String(chars2);
+ char[] chars3 = new char[32];
+ stringData[RANDOM_STRING_32].getChars(0, 32, chars3, 0);
+ stringNewStringFromCharsResult[RANDOM_STRING_32] = new String(chars3);
+ }
+
+ @Benchmark
+ public void jmhTimeStringNewStringFromCharsLarge() {
+ char[] chars = new char[128];
+ stringData[RANDOM_STRING_128].getChars(0, 128, chars, 0);
+ stringNewStringFromCharsResult[RANDOM_STRING_128] = new String(chars);
+ char[] chars2 = new char[512];
+ stringData[RANDOM_STRING_512].getChars(0, 512, chars2, 0);
+ stringNewStringFromCharsResult[RANDOM_STRING_512] = new String(chars2);
+ }
+
+ /**
+ * NewStringFromString
+ */
+
+ @Benchmark
+ public void jmhTimeStringNewStringFromStringSmall() {
+ stringNewStringFromStringResult[RANDOM_STRING_8] =
+ new String(stringData[RANDOM_STRING_8]);
+ stringNewStringFromStringResult[RANDOM_STRING_16] =
+ new String(stringData[RANDOM_STRING_16]);
+ stringNewStringFromStringResult[RANDOM_STRING_32] =
+ new String(stringData[RANDOM_STRING_32]);
+ }
+
+ @Benchmark
+ public void jmhTimeStringNewStringFromStringLarge() {
+ stringNewStringFromStringResult[RANDOM_STRING_128] =
+ new String(stringData[RANDOM_STRING_128]);
+ stringNewStringFromStringResult[RANDOM_STRING_512] =
+ new String(stringData[RANDOM_STRING_512]);
+ }
+
+ /**
+ * String.getCharsNoCheck
+ */
+
+ @Benchmark
+ public void jmhTimeStringGetCharsNoCheckSmall() {
+ stringData[RANDOM_STRING_8].getChars(0, 8, chars_8, 0);
+ stringGetCharsNoCheckResult[RANDOM_STRING_8] = new String(chars_8);
+ stringData[RANDOM_STRING_16].getChars(0, 16, chars_16, 0);
+ stringGetCharsNoCheckResult[RANDOM_STRING_16] = new String(chars_16);
+ stringData[RANDOM_STRING_32].getChars(0, 32, chars_32, 0);
+ stringGetCharsNoCheckResult[RANDOM_STRING_32] = new String(chars_32);
+ }
+
+ @Benchmark
+ public void jmhTimeStringGetCharsNoCheckLarge() {
+ stringData[RANDOM_STRING_128].getChars(0, 128, chars_128, 0);
+ stringGetCharsNoCheckResult[RANDOM_STRING_128] = new String(chars_128);
+ stringData[RANDOM_STRING_512].getChars(0, 512, chars_512, 0);
+ stringGetCharsNoCheckResult[RANDOM_STRING_512] = new String(chars_512);
+ }
+}