diff options
author | Ningsheng Jian <ningsheng.jian@linaro.org> | 2017-11-07 18:38:01 +0800 |
---|---|---|
committer | Ningsheng Jian <ningsheng.jian@linaro.org> | 2017-11-16 09:46:55 +0800 |
commit | e715fe64e96acb6131af937d0c8bba2537ea13f4 (patch) | |
tree | 702384eb404c3fd6acbbc3321261847e9fc27398 /src/main/java/org/linaro/benchmarks/micro/StringOps.java | |
parent | 3811e9930ddb1d2b3a1463ad6c876af324331335 (diff) |
1. Port benchmark cases from art-testing.
2. Add some more benchmarks for basic OPs.
3. Fix some jmh result variance.
Signed-off-by: Zhongwei Yao <zhongwei.yao@linaro.org>
Signed-off-by: Yang Zhang <yang.zhang@linaro.org>
Signed-off-by: Ningsheng Jian <ningsheng.jian@linaro.org>
Change-Id: I514658696b63e468158325be3b84494553773705
Diffstat (limited to 'src/main/java/org/linaro/benchmarks/micro/StringOps.java')
-rw-r--r-- | src/main/java/org/linaro/benchmarks/micro/StringOps.java | 425 |
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); + } +} |