diff --git a/apct-tests/perftests/core/Android.bp b/apct-tests/perftests/core/Android.bp index 2182f0bc2501..23464f879518 100644 --- a/apct-tests/perftests/core/Android.bp +++ b/apct-tests/perftests/core/Android.bp @@ -43,12 +43,13 @@ android_test { "apct-perftests-resources-manager-apps", "apct-perftests-utils", "collector-device-lib", + "core-tests-support", "guava", ], libs: ["android.test.base"], - java_resources: [ ":GoogleFontDancingScript", ], + java_resources: [":GoogleFontDancingScript"], data: [":perfetto_artifacts"], diff --git a/apct-tests/perftests/core/src/android/libcore/nor_ready/JarFilePerfTest.java b/apct-tests/perftests/core/src/android/libcore/nor_ready/JarFilePerfTest.java new file mode 100644 index 000000000000..5ad5eea60aae --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/nor_ready/JarFilePerfTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * 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. + */ + +package android.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.io.File; +import java.util.Arrays; +import java.util.Collection; +import java.util.jar.JarFile; +import java.util.jar.Manifest; + +@RunWith(Parameterized.class) +@LargeTest +public class JarFilePerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Parameters(name = "mFilename={0}") + public static Collection data() { + return Arrays.asList( + new Object[][] { + {"/system/framework/core-oj.jar"}, {"/system/priv-app/Phonesky/Phonesky.apk"} + }); + } + + @Parameterized.Parameter(0) + public String mFilename; + + @Test + public void time() throws Exception { + File f = new File(mFilename); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + JarFile jf = new JarFile(f); + Manifest m = jf.getManifest(); + jf.close(); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/SSLLoopbackPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/SSLLoopbackPerfTest.java new file mode 100644 index 000000000000..694d609cd950 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/SSLLoopbackPerfTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * 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. + */ + +package android.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import androidx.test.runner.AndroidJUnit4; + +import libcore.java.security.TestKeyStore; +import libcore.javax.net.ssl.TestSSLContext; +import libcore.javax.net.ssl.TestSSLSocketPair; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.net.ssl.SSLSocket; + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class SSLLoopbackPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Test + public void time() throws Exception { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + TestSSLContext context = + TestSSLContext.create(TestKeyStore.getClient(), TestKeyStore.getServer()); + SSLSocket[] sockets = TestSSLSocketPair.connect(context, null, null); + context.close(); + sockets[0].close(); + sockets[1].close(); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/SSLSocketFactoryPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/SSLSocketFactoryPerfTest.java new file mode 100644 index 000000000000..bdbbcb0da006 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/SSLSocketFactoryPerfTest.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * 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. + */ + +package android.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.net.ssl.SSLSocketFactory; + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class SSLSocketFactoryPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Test + public void time() throws Exception { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + SSLSocketFactory.getDefault(); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/SchemePrefixPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/SchemePrefixPerfTest.java new file mode 100644 index 000000000000..42dc5811e6db --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/SchemePrefixPerfTest.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * 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. + */ + +package android.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +@RunWith(Parameterized.class) +@LargeTest +public final class SchemePrefixPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + enum Strategy { + JAVA() { + @Override + String execute(String spec) { + int colon = spec.indexOf(':'); + + if (colon < 1) { + return null; + } + + for (int i = 0; i < colon; i++) { + char c = spec.charAt(i); + if (!isValidSchemeChar(i, c)) { + return null; + } + } + + return spec.substring(0, colon).toLowerCase(Locale.US); + } + + private boolean isValidSchemeChar(int index, char c) { + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { + return true; + } + if (index > 0 && ((c >= '0' && c <= '9') || c == '+' || c == '-' || c == '.')) { + return true; + } + return false; + } + }, + + REGEX() { + private final Pattern mPattern = Pattern.compile("^([a-zA-Z][a-zA-Z0-9+\\-.]*):"); + + @Override + String execute(String spec) { + Matcher matcher = mPattern.matcher(spec); + if (matcher.find()) { + return matcher.group(1).toLowerCase(Locale.US); + } else { + return null; + } + } + }; + + abstract String execute(String spec); + } + + @Parameters(name = "mStrategy={0}") + public static Collection data() { + return Arrays.asList(new Object[][] {{Strategy.REGEX}, {Strategy.JAVA}}); + } + + @Parameterized.Parameter(0) + public Strategy mStrategy; + + @Test + public void timeSchemePrefix() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStrategy.execute("http://android.com"); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/SerializationPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/SerializationPerfTest.java new file mode 100644 index 000000000000..1ec22d217109 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/SerializationPerfTest.java @@ -0,0 +1,292 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * 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. + */ + +package android.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamClass; +import java.io.Serializable; +import java.util.ArrayList; + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class SerializationPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + private static byte[] bytes(Object o) throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); + ObjectOutputStream out = new ObjectOutputStream(baos); + out.writeObject(o); + out.close(); + return baos.toByteArray(); + } + + @Test + public void timeReadIntArray() throws Exception { + int[] intArray = new int[256]; + readSingleObject(intArray); + } + + @Test + public void timeWriteIntArray() throws Exception { + int[] intArray = new int[256]; + writeSingleObject(intArray); + } + + @Test + public void timeReadArrayListInteger() throws Exception { + ArrayList object = new ArrayList(); + for (int i = 0; i < 256; ++i) { + object.add(i); + } + readSingleObject(object); + } + + @Test + public void timeWriteArrayListInteger() throws Exception { + ArrayList object = new ArrayList(); + for (int i = 0; i < 256; ++i) { + object.add(i); + } + writeSingleObject(object); + } + + @Test + public void timeReadString() throws Exception { + readSingleObject("hello"); + } + + @Test + public void timeReadObjectStreamClass() throws Exception { + // A special case because serialization itself requires this class. + // (This should really be a unit test.) + ObjectStreamClass osc = ObjectStreamClass.lookup(String.class); + readSingleObject(osc); + } + + @Test + public void timeWriteString() throws Exception { + // String is a special case that avoids JNI. + writeSingleObject("hello"); + } + + @Test + public void timeWriteObjectStreamClass() throws Exception { + // A special case because serialization itself requires this class. + // (This should really be a unit test.) + ObjectStreamClass osc = ObjectStreamClass.lookup(String.class); + writeSingleObject(osc); + } + + // This is + // + // @Testa baseline for the others. + public void timeWriteNoObjects() throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); + ObjectOutputStream out = new ObjectOutputStream(baos); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + out.reset(); + baos.reset(); + } + out.close(); + } + + private void readSingleObject(Object object) throws Exception { + byte[] bytes = bytes(object); + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + ObjectInputStream in = new ObjectInputStream(bais); + in.readObject(); + in.close(); + bais.reset(); + } + } + + private void writeSingleObject(Object o) throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); + ObjectOutputStream out = new ObjectOutputStream(baos); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + out.writeObject(o); + out.reset(); + baos.reset(); + } + out.close(); + } + + @Test + public void timeWriteEveryKindOfField() throws Exception { + writeSingleObject(new LittleBitOfEverything()); + } + + @Test + public void timeWriteSerializableBoolean() throws Exception { + writeSingleObject(new SerializableBoolean()); + } + + @Test + public void timeWriteSerializableByte() throws Exception { + writeSingleObject(new SerializableByte()); + } + + @Test + public void timeWriteSerializableChar() throws Exception { + writeSingleObject(new SerializableChar()); + } + + @Test + public void timeWriteSerializableDouble() throws Exception { + writeSingleObject(new SerializableDouble()); + } + + @Test + public void timeWriteSerializableFloat() throws Exception { + writeSingleObject(new SerializableFloat()); + } + + @Test + public void timeWriteSerializableInt() throws Exception { + writeSingleObject(new SerializableInt()); + } + + @Test + public void timeWriteSerializableLong() throws Exception { + writeSingleObject(new SerializableLong()); + } + + @Test + public void timeWriteSerializableShort() throws Exception { + writeSingleObject(new SerializableShort()); + } + + @Test + public void timeWriteSerializableReference() throws Exception { + writeSingleObject(new SerializableReference()); + } + + @Test + public void timeReadEveryKindOfField() throws Exception { + readSingleObject(new LittleBitOfEverything()); + } + + @Test + public void timeReadSerializableBoolean() throws Exception { + readSingleObject(new SerializableBoolean()); + } + + @Test + public void timeReadSerializableByte() throws Exception { + readSingleObject(new SerializableByte()); + } + + @Test + public void timeReadSerializableChar() throws Exception { + readSingleObject(new SerializableChar()); + } + + @Test + public void timeReadSerializableDouble() throws Exception { + readSingleObject(new SerializableDouble()); + } + + @Test + public void timeReadSerializableFloat() throws Exception { + readSingleObject(new SerializableFloat()); + } + + @Test + public void timeReadSerializableInt() throws Exception { + readSingleObject(new SerializableInt()); + } + + @Test + public void timeReadSerializableLong() throws Exception { + readSingleObject(new SerializableLong()); + } + + @Test + public void timeReadSerializableShort() throws Exception { + readSingleObject(new SerializableShort()); + } + + @Test + public void timeReadSerializableReference() throws Exception { + readSingleObject(new SerializableReference()); + } + + public static class SerializableBoolean implements Serializable { + boolean mZ; + } + + public static class SerializableByte implements Serializable { + byte mB; + } + + public static class SerializableChar implements Serializable { + char mC; + } + + public static class SerializableDouble implements Serializable { + double mD; + } + + public static class SerializableFloat implements Serializable { + float mF; + } + + public static class SerializableInt implements Serializable { + int mI; + } + + public static class SerializableLong implements Serializable { + long mJ; + } + + public static class SerializableShort implements Serializable { + short mS; + } + + public static class SerializableReference implements Serializable { + Object mL; + } + + public static class LittleBitOfEverything implements Serializable { + boolean mZ; + byte mB; + char mC; + double mD; + float mF; + int mI; + long mJ; + short mS; + Object mL; + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/SignaturePerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/SignaturePerfTest.java new file mode 100644 index 000000000000..a1899b92cff7 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/SignaturePerfTest.java @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * 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. + */ +package android.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.Signature; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** Tests RSA and DSA mSignature creation and verification. */ +@RunWith(Parameterized.class) +@LargeTest +public class SignaturePerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Parameters(name = "mAlgorithm={0}, mImplementation={1}") + public static Collection data() { + return Arrays.asList( + new Object[][] { + {Algorithm.MD5WithRSA, Implementation.OpenSSL}, + {Algorithm.SHA1WithRSA, Implementation.OpenSSL}, + {Algorithm.SHA256WithRSA, Implementation.OpenSSL}, + {Algorithm.SHA384WithRSA, Implementation.OpenSSL}, + {Algorithm.SHA512WithRSA, Implementation.OpenSSL}, + {Algorithm.SHA1withDSA, Implementation.OpenSSL}, + {Algorithm.SHA1withDSA, Implementation.BouncyCastle} + }); + } + + @Parameterized.Parameter(0) + public Algorithm mAlgorithm; + + @Parameterized.Parameter(1) + public Implementation mImplementation; + + private static final int DATA_SIZE = 8192; + private static final byte[] DATA = new byte[DATA_SIZE]; + + static { + for (int i = 0; i < DATA_SIZE; i++) { + DATA[i] = (byte) i; + } + } + + public enum Algorithm { + MD5WithRSA, + SHA1WithRSA, + SHA256WithRSA, + SHA384WithRSA, + SHA512WithRSA, + SHA1withDSA + }; + + public enum Implementation { + OpenSSL, + BouncyCastle + }; + + // Key generation and signing aren't part of the benchmark for verification + // so cache the results + private static Map sKeyPairs = new HashMap(); + private static Map sSignatures = new HashMap(); + + private String mSignatureAlgorithm; + private byte[] mSignature; + private PrivateKey mPrivateKey; + private PublicKey mPublicKey; + + @Before + public void setUp() throws Exception { + this.mSignatureAlgorithm = mAlgorithm.toString(); + + String keyAlgorithm = + mSignatureAlgorithm.substring( + mSignatureAlgorithm.length() - 3, mSignatureAlgorithm.length()); + KeyPair keyPair = sKeyPairs.get(keyAlgorithm); + if (keyPair == null) { + KeyPairGenerator generator = KeyPairGenerator.getInstance(keyAlgorithm); + keyPair = generator.generateKeyPair(); + sKeyPairs.put(keyAlgorithm, keyPair); + } + this.mPrivateKey = keyPair.getPrivate(); + this.mPublicKey = keyPair.getPublic(); + + this.mSignature = sSignatures.get(mSignatureAlgorithm); + if (this.mSignature == null) { + Signature signer = Signature.getInstance(mSignatureAlgorithm); + signer.initSign(keyPair.getPrivate()); + signer.update(DATA); + this.mSignature = signer.sign(); + sSignatures.put(mSignatureAlgorithm, mSignature); + } + } + + @Test + public void timeSign() throws Exception { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + Signature signer; + switch (mImplementation) { + case OpenSSL: + signer = Signature.getInstance(mSignatureAlgorithm, "AndroidOpenSSL"); + break; + case BouncyCastle: + signer = Signature.getInstance(mSignatureAlgorithm, "BC"); + break; + default: + throw new RuntimeException(mImplementation.toString()); + } + signer.initSign(mPrivateKey); + signer.update(DATA); + signer.sign(); + } + } + + @Test + public void timeVerify() throws Exception { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + Signature verifier; + switch (mImplementation) { + case OpenSSL: + verifier = Signature.getInstance(mSignatureAlgorithm, "AndroidOpenSSL"); + break; + case BouncyCastle: + verifier = Signature.getInstance(mSignatureAlgorithm, "BC"); + break; + default: + throw new RuntimeException(mImplementation.toString()); + } + verifier.initVerify(mPublicKey); + verifier.update(DATA); + verifier.verify(mSignature); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/SimpleDateFormatPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/SimpleDateFormatPerfTest.java new file mode 100644 index 000000000000..c25b0ce6d7d9 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/SimpleDateFormatPerfTest.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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. + */ + +package android.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Benchmark for java.text.SimpleDateFormat. This tests common formatting, parsing and creation + * operations with a specific focus on TimeZone handling. + */ +@RunWith(AndroidJUnit4.class) +@LargeTest +public class SimpleDateFormatPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Test + public void time_createFormatWithTimeZone() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd z"); + } + } + + @Test + public void time_parseWithTimeZoneShort() throws ParseException { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd z"); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + sdf.parse("2000.01.01 PST"); + } + } + + @Test + public void time_parseWithTimeZoneLong() throws ParseException { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd zzzz"); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + sdf.parse("2000.01.01 Pacific Standard Time"); + } + } + + @Test + public void time_parseWithoutTimeZone() throws ParseException { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd"); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + sdf.parse("2000.01.01"); + } + } + + @Test + public void time_createAndParseWithTimeZoneShort() throws ParseException { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd z"); + sdf.parse("2000.01.01 PST"); + } + } + + @Test + public void time_createAndParseWithTimeZoneLong() throws ParseException { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd zzzz"); + sdf.parse("2000.01.01 Pacific Standard Time"); + } + } + + @Test + public void time_formatWithTimeZoneShort() { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd z"); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + sdf.format(new Date()); + } + } + + @Test + public void time_formatWithTimeZoneLong() { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd zzzz"); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + sdf.format(new Date()); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StrictMathPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StrictMathPerfTest.java new file mode 100644 index 000000000000..eeccb5bd64f4 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/StrictMathPerfTest.java @@ -0,0 +1,510 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * 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. + */ + +package android.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Many of these tests are bogus in that the cost will vary wildly depending on inputs. For _my_ + * current purposes, that's okay. But beware! + */ +@RunWith(AndroidJUnit4.class) +@LargeTest +public class StrictMathPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + private final double mDouble = 1.2; + private final float mFloat = 1.2f; + private final int mInt = 1; + private final long mLong = 1L; + + /* Values for full line coverage of ceiling function */ + private static final double[] CEIL_DOUBLES = + new double[] { + 3245817.2018463886, + 1418139.083668501, + 3.572936802189103E15, + -4.7828929737254625E249, + 213596.58636369856, + 6.891928421440976E-96, + -7.9318566885477E-36, + -1.9610339084804148E15, + -4.696725715628246E10, + 3742491.296880909, + 7.140274745333553E11 + }; + + /* Values for full line coverage of floor function */ + private static final double[] FLOOR_DOUBLES = + new double[] { + 7.140274745333553E11, + 3742491.296880909, + -4.696725715628246E10, + -1.9610339084804148E15, + 7.049948629370372E-56, + -7.702933170334643E-16, + -1.99657681810579, + -1.1659287182288336E236, + 4.085518816513057E15, + -1500948.440658056, + -2.2316479921415575E7 + }; + + @Test + public void timeAbsD() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.abs(mDouble); + } + } + + @Test + public void timeAbsF() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.abs(mFloat); + } + } + + @Test + public void timeAbsI() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.abs(mInt); + } + } + + @Test + public void timeAbsL() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.abs(mLong); + } + } + + @Test + public void timeAcos() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.acos(mDouble); + } + } + + @Test + public void timeAsin() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.asin(mDouble); + } + } + + @Test + public void timeAtan() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.atan(mDouble); + } + } + + @Test + public void timeAtan2() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.atan2(3, 4); + } + } + + @Test + public void timeCbrt() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.cbrt(mDouble); + } + } + + @Test + public void timeCeilOverInterestingValues() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + for (int i = 0; i < CEIL_DOUBLES.length; ++i) { + StrictMath.ceil(CEIL_DOUBLES[i]); + } + } + } + + @Test + public void timeCopySignD() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.copySign(mDouble, mDouble); + } + } + + @Test + public void timeCopySignF() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.copySign(mFloat, mFloat); + } + } + + @Test + public void timeCos() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.cos(mDouble); + } + } + + @Test + public void timeCosh() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.cosh(mDouble); + } + } + + @Test + public void timeExp() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.exp(mDouble); + } + } + + @Test + public void timeExpm1() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.expm1(mDouble); + } + } + + @Test + public void timeFloorOverInterestingValues() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + for (int i = 0; i < FLOOR_DOUBLES.length; ++i) { + StrictMath.floor(FLOOR_DOUBLES[i]); + } + } + } + + @Test + public void timeGetExponentD() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.getExponent(mDouble); + } + } + + @Test + public void timeGetExponentF() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.getExponent(mFloat); + } + } + + @Test + public void timeHypot() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.hypot(mDouble, mDouble); + } + } + + @Test + public void timeIEEEremainder() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.IEEEremainder(mDouble, mDouble); + } + } + + @Test + public void timeLog() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.log(mDouble); + } + } + + @Test + public void timeLog10() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.log10(mDouble); + } + } + + @Test + public void timeLog1p() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.log1p(mDouble); + } + } + + @Test + public void timeMaxD() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.max(mDouble, mDouble); + } + } + + @Test + public void timeMaxF() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.max(mFloat, mFloat); + } + } + + @Test + public void timeMaxI() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.max(mInt, mInt); + } + } + + @Test + public void timeMaxL() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.max(mLong, mLong); + } + } + + @Test + public void timeMinD() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.min(mDouble, mDouble); + } + } + + @Test + public void timeMinF() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.min(mFloat, mFloat); + } + } + + @Test + public void timeMinI() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.min(mInt, mInt); + } + } + + @Test + public void timeMinL() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.min(mLong, mLong); + } + } + + @Test + public void timeNextAfterD() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.nextAfter(mDouble, mDouble); + } + } + + @Test + public void timeNextAfterF() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.nextAfter(mFloat, mFloat); + } + } + + @Test + public void timeNextUpD() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.nextUp(mDouble); + } + } + + @Test + public void timeNextUpF() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.nextUp(mFloat); + } + } + + @Test + public void timePow() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.pow(mDouble, mDouble); + } + } + + @Test + public void timeRandom() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.random(); + } + } + + @Test + public void timeRint() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.rint(mDouble); + } + } + + @Test + public void timeRoundD() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.round(mDouble); + } + } + + @Test + public void timeRoundF() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.round(mFloat); + } + } + + @Test + public void timeScalbD() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.scalb(mDouble, 5); + } + } + + @Test + public void timeScalbF() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.scalb(mFloat, 5); + } + } + + @Test + public void timeSignumD() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.signum(mDouble); + } + } + + @Test + public void timeSignumF() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.signum(mFloat); + } + } + + @Test + public void timeSin() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.sin(mDouble); + } + } + + @Test + public void timeSinh() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.sinh(mDouble); + } + } + + @Test + public void timeSqrt() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.sqrt(mDouble); + } + } + + @Test + public void timeTan() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.tan(mDouble); + } + } + + @Test + public void timeTanh() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.tanh(mDouble); + } + } + + @Test + public void timeToDegrees() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.toDegrees(mDouble); + } + } + + @Test + public void timeToRadians() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.toRadians(mDouble); + } + } + + @Test + public void timeUlpD() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.ulp(mDouble); + } + } + + @Test + public void timeUlpF() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StrictMath.ulp(mFloat); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringBuilderPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringBuilderPerfTest.java new file mode 100644 index 000000000000..34fb88bf8627 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/StringBuilderPerfTest.java @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * 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. + */ + +package android.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.Arrays; +import java.util.Collection; + +/** Tests the performance of various StringBuilder methods. */ +@RunWith(Parameterized.class) +@LargeTest +public class StringBuilderPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Parameters(name = "mLength={0}") + public static Collection data() { + return Arrays.asList(new Object[][] {{1}, {10}, {100}}); + } + + @Parameterized.Parameter(0) + public int mLength; + + @Test + public void timeAppendBoolean() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < mLength; ++j) { + sb.append(true); + } + } + } + + @Test + public void timeAppendChar() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < mLength; ++j) { + sb.append('c'); + } + } + } + + @Test + public void timeAppendCharArray() { + char[] chars = "chars".toCharArray(); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < mLength; ++j) { + sb.append(chars); + } + } + } + + @Test + public void timeAppendCharSequence() { + CharSequence cs = "chars"; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < mLength; ++j) { + sb.append(cs); + } + } + } + + @Test + public void timeAppendSubCharSequence() { + CharSequence cs = "chars"; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < mLength; ++j) { + sb.append(cs); + } + } + } + + @Test + public void timeAppendDouble() { + double d = 1.2; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < mLength; ++j) { + sb.append(d); + } + } + } + + @Test + public void timeAppendFloat() { + float f = 1.2f; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < mLength; ++j) { + sb.append(f); + } + } + } + + @Test + public void timeAppendInt() { + int n = 123; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < mLength; ++j) { + sb.append(n); + } + } + } + + @Test + public void timeAppendLong() { + long l = 123; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < mLength; ++j) { + sb.append(l); + } + } + } + + @Test + public void timeAppendObject() { + // We don't want to time the toString, so ensure we're calling a trivial one... + Object o = + new Object() { + @Override + public String toString() { + return "constant"; + } + }; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < mLength; ++j) { + sb.append(o); + } + } + } + + @Test + public void timeAppendString() { + String s = "chars"; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + StringBuilder sb = new StringBuilder(); + for (int j = 0; j < mLength; ++j) { + sb.append(s); + } + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringEqualsPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringEqualsPerfTest.java new file mode 100644 index 000000000000..6854c0de9387 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/StringEqualsPerfTest.java @@ -0,0 +1,313 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * 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. + */ + +package android.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import androidx.test.runner.AndroidJUnit4; + +import junit.framework.Assert; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Benchmarks to measure the performance of String.equals for Strings of varying lengths. Each + * benchmarks makes 5 measurements, aiming at covering cases like strings of equal length that are + * not equal, identical strings with different references, strings with different endings, interned + * strings, and strings of different lengths. + */ +@RunWith(AndroidJUnit4.class) +@LargeTest +public class StringEqualsPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + private final String mLong1 = + "Ahead-of-time compilation is possible as the compiler may just convert an instruction" + + " thus: dex code: add-int v1000, v2000, v3000 C code: setIntRegter(1000," + + " call_dex_add_int(getIntRegister(2000), getIntRegister(3000)) This means even" + + " lidinstructions may have code generated, however, it is not expected that code" + + " generate inthis way will perform well. The job of AOT verification is to tell" + + " the compiler thatinstructions are sound and provide tests to detect unsound" + + " sequences so slow path codemay be generated. Other than for totally invalid" + + " code, the verification may fail at AOrrun-time. At AOT time it can be because" + + " of incomplete information, at run-time it can ethat code in a different apk" + + " that the application depends upon has changed. The Dalvikverifier would return" + + " a bool to state whether a Class were good or bad. In ART the fail case becomes" + + " either a soft or hard failure. Classes have new states to represent that a soft" + + " failure occurred at compile time and should be re-verified at run-time."; + + private final String mVeryLong = + "Garbage collection has two phases. The first distinguishes live objects from garbage" + + " objects. The second is reclaiming the rage of garbage objectIn the mark-sweep" + + " algorithm used by Dalvik, the first phase is achievd by computing the closure" + + " of all reachable objects in a process known as tracing from theoots. After" + + " thetrace has completed, garbage objects are reclaimed. Each of these" + + " operations can beparallelized and can be interleaved with the operation of the" + + " applicationTraditionally,the tracing phase dominates the time spent in garbage" + + " collection. The greatreduction ipause time can be achieved by interleaving as" + + " much of this phase as possible with theapplication. If we simply ran the GC in" + + " a separate thread with no other changes, normaloperation of an application" + + " would confound the trace. Abstractly, the GC walks the h oall reachable" + + " objects. When the application is paused, the object graph cannot change.The GC" + + " can therefore walk this structure and assume that all reachable objects" + + " live.When the application is running, this graph may be altered. New nodes may" + + " be addnd edgemay be changed. These changes may cause live objects to be hidden" + + " and falsely recla bythe GC. To avoid this problem a write barrier is used to" + + " intercept and record modifionto objects in a separate structure. After" + + " performing its walk, the GC will revisit theupdated objects and re-validate its" + + " assumptions. Without a card table, the garbagecollector would have to visit" + + " all objects reached during the trace looking for dirtied objects. The cost of" + + " this operation would be proportional to the amount of live data.With a card" + + " table, the cost of this operation is proportional to the amount of updateatThe" + + " write barrier in Dalvik is a card marking write barrier. Card marking is the" + + " proceof noting the location of object connectivity changes on a sub-page" + + " granularity. A caris merely a colorful term for a contiguous extent of memory" + + " smaller than a page, commonsomewhere between 128- and 512-bytes. Card marking" + + " is implemented by instrumenting alllocations in the virtual machine which can" + + " assign a pointer to an object. After themalpointer assignment has occurred, a" + + " byte is written to a byte-map spanning the heap whiccorresponds to the location" + + " of the updated object. This byte map is known as a card taThe garbage" + + " collector visits this card table and looks for written bytes to reckon" + + " thelocation of updated objects. It then rescans all objects located on the" + + " dirty card,correcting liveness assumptions that were invalidated by the" + + " application. While cardmarking imposes a small burden on the application" + + " outside of a garbage collection, theoverhead of maintaining the card table is" + + " paid for by the reduced time spent insidegarbage collection. With the" + + " concurrent garbage collection thread and a write barriersupported by the" + + " interpreter, JIT, and Runtime we modify garbage collection"; + + private final String[][] mShortStrings = + new String[][] { + // Equal, constant comparison + {"a", "a"}, + // Different constants, first character different + {":", " :"}, + // Different constants, last character different, same length + {"ja M", "ja N"}, + // Different constants, different lengths + {"$$$", "$$"}, + // Force execution of code beyond reference equality check + {"hi", new String("hi")} + }; + + private final String[][] mMediumStrings = + new String[][] { + // Equal, constant comparison + {"Hello my name is ", "Hello my name is "}, + // Different constants, different lengths + {"What's your name?", "Whats your name?"}, + // Force execution of code beyond reference equality check + {"Android Runtime", new String("Android Runtime")}, + // Different constants, last character different, same length + {"v3ry Cre@tiVe?****", "v3ry Cre@tiVe?***."}, + // Different constants, first character different, same length + {"!@#$%^&*()_++*^$#@", "0@#$%^&*()_++*^$#@"} + }; + + private final String[][] mLongStrings = + new String[][] { + // Force execution of code beyond reference equality check + {mLong1, new String(mLong1)}, + // Different constants, last character different, same length + {mLong1 + "fun!", mLong1 + "----"}, + // Equal, constant comparison + {mLong1 + mLong1, mLong1 + mLong1}, + // Different constants, different lengths + {mLong1 + "123456789", mLong1 + "12345678"}, + // Different constants, first character different, same length + {"Android Runtime" + mLong1, "android Runtime" + mLong1} + }; + + private final String[][] mVeryLongStrings = + new String[][] { + // Force execution of code beyond reference equality check + {mVeryLong, new String(mVeryLong)}, + // Different constants, different lengths + {mVeryLong + mVeryLong, mVeryLong + " " + mVeryLong}, + // Equal, constant comparison + {mVeryLong + mVeryLong + mVeryLong, mVeryLong + mVeryLong + mVeryLong}, + // Different constants, last character different, same length + {mVeryLong + "77777", mVeryLong + "99999"}, + // Different constants, first character different + {"Android Runtime" + mVeryLong, "android Runtime" + mVeryLong} + }; + + private final String[][] mEndStrings = + new String[][] { + // Different constants, medium but different lengths + {"Hello", "Hello "}, + // Different constants, long but different lengths + {mLong1, mLong1 + "x"}, + // Different constants, very long but different lengths + {mVeryLong, mVeryLong + "?"}, + // Different constants, same medium lengths + {"How are you doing today?", "How are you doing today "}, + // Different constants, short but different lengths + {"1", "1."} + }; + + private final String mTmpStr1 = + "012345678901234567890" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789"; + + private final String mTmpStr2 = + "z012345678901234567890" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "0123456789012345678901234567890123456789" + + "012345678901234567890123456789012345678x"; + + private final String[][] mNonalignedStrings = + new String[][] { + // Different non-word aligned medium length strings + {mTmpStr1, mTmpStr1.substring(1)}, + // Different differently non-word aligned medium length strings + {mTmpStr2, mTmpStr2.substring(2)}, + // Different non-word aligned long length strings + {mLong1, mLong1.substring(3)}, + // Different non-word aligned very long length strings + {mVeryLong, mVeryLong.substring(1)}, + // Equal non-word aligned constant strings + {"hello", "hello".substring(1)} + }; + + private final Object[] mObjects = + new Object[] { + // Compare to Double object + new Double(1.5), + // Compare to Integer object + new Integer(9999999), + // Compare to String array + new String[] {"h", "i"}, + // Compare to int array + new int[] {1, 2, 3}, + // Compare to Character object + new Character('a') + }; + + // Check assumptions about how the compiler, new String(String), and String.intern() work. + // Any failures here would invalidate these benchmarks. + @Before + public void setUp() throws Exception { + // String constants are the same object + Assert.assertSame("abc", "abc"); + // new String(String) makes a copy + Assert.assertNotSame("abc", new String("abc")); + // Interned strings are treated like constants, so it is not necessary to + // separately benchmark interned strings. + Assert.assertSame("abc", "abc".intern()); + Assert.assertSame("abc", new String("abc").intern()); + // Compiler folds constant strings into new constants + Assert.assertSame(mLong1 + mLong1, mLong1 + mLong1); + } + + // Benchmark cases of String.equals(null) + @Test + public void timeEqualsNull() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + for (int i = 0; i < mMediumStrings.length; i++) { + mMediumStrings[i][0].equals(null); + } + } + } + + // Benchmark cases with very short (<5 character) Strings + @Test + public void timeEqualsShort() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + for (int i = 0; i < mShortStrings.length; i++) { + mShortStrings[i][0].equals(mShortStrings[i][1]); + } + } + } + + // Benchmark cases with medium length (10-15 character) Strings + @Test + public void timeEqualsMedium() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + for (int i = 0; i < mMediumStrings.length; i++) { + mMediumStrings[i][0].equals(mMediumStrings[i][1]); + } + } + } + + // Benchmark cases with long (>100 character) Strings + @Test + public void timeEqualsLong() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + for (int i = 0; i < mLongStrings.length; i++) { + mLongStrings[i][0].equals(mLongStrings[i][1]); + } + } + } + + // Benchmark cases with very long (>1000 character) Strings + @Test + public void timeEqualsVeryLong() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + for (int i = 0; i < mVeryLongStrings.length; i++) { + mVeryLongStrings[i][0].equals(mVeryLongStrings[i][1]); + } + } + } + + // Benchmark cases with non-word aligned Strings + @Test + public void timeEqualsNonWordAligned() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + for (int i = 0; i < mNonalignedStrings.length; i++) { + mNonalignedStrings[i][0].equals(mNonalignedStrings[i][1]); + } + } + } + + // Benchmark cases with slight differences in the endings + @Test + public void timeEqualsEnd() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + for (int i = 0; i < mEndStrings.length; i++) { + mEndStrings[i][0].equals(mEndStrings[i][1]); + } + } + } + + // Benchmark cases of comparing a string to a non-string object + @Test + public void timeEqualsNonString() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + for (int i = 0; i < mMediumStrings.length; i++) { + mMediumStrings[i][0].equals(mObjects[i]); + } + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringIsEmptyPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringIsEmptyPerfTest.java new file mode 100644 index 000000000000..79ff646bbfff --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/StringIsEmptyPerfTest.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * 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. + */ + +package android.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class StringIsEmptyPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Test + public void timeIsEmpty_NonEmpty() { + boolean result = true; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + result &= !("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".isEmpty()); + } + if (!result) throw new RuntimeException(); + } + + @Test + public void timeIsEmpty_Empty() { + boolean result = true; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + result &= ("".isEmpty()); + } + if (!result) throw new RuntimeException(); + } + + @Test + public void timeLengthEqualsZero() { + boolean result = true; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + result &= !("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".length() == 0); + } + if (!result) throw new RuntimeException(); + } + + @Test + public void timeEqualsEmpty() { + boolean result = true; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + result &= !"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".equals(""); + } + if (!result) throw new RuntimeException(); + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringLengthPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringLengthPerfTest.java new file mode 100644 index 000000000000..8dbf9f58fbf8 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/StringLengthPerfTest.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * 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. + */ + +package android.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class StringLengthPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Test + public void timeLength() { + int length = 0; + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + length = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".length(); + } + if (length != 51) throw new RuntimeException(); + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringPerfTest.java new file mode 100644 index 000000000000..02194b1b9745 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/StringPerfTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * 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. + */ + +package android.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.Arrays; +import java.util.Collection; + +@RunWith(Parameterized.class) +@LargeTest +public class StringPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + enum StringLengths { + EMPTY(""), + SHORT("short"), + EIGHTY(makeString(80)), + EIGHT_KI(makeString(8192)); + final String mValue; + + StringLengths(String value) { + this.mValue = value; + } + } + + @Parameters(name = "mStringLengths={0}") + public static Collection data() { + return Arrays.asList( + new Object[][] { + {StringLengths.EIGHT_KI}, + {StringLengths.EIGHTY}, + {StringLengths.SHORT}, + {StringLengths.EMPTY} + }); + } + + @Parameterized.Parameter(0) + public StringLengths mStringLengths; + + private static String makeString(int length) { + StringBuilder result = new StringBuilder(length); + for (int i = 0; i < length; ++i) { + result.append((char) i); + } + return result.toString(); + } + + @Test + public void timeHashCode() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.hashCode(); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringReplaceAllPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringReplaceAllPerfTest.java new file mode 100644 index 000000000000..b0d1ee4132fa --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/StringReplaceAllPerfTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * 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. + */ + +package android.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.Arrays; +import java.util.Collection; + +@RunWith(Parameterized.class) +@LargeTest +public class StringReplaceAllPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + // NOTE: These estimates of MOVEABLE / NON_MOVEABLE are based on a knowledge of + // ART implementation details. They make a difference here because JNI calls related + // to strings took different paths depending on whether the String in question was + // moveable or not. + enum StringLengths { + EMPTY(""), + MOVEABLE_16(makeString(16)), + MOVEABLE_256(makeString(256)), + MOVEABLE_1024(makeString(1024)), + NON_MOVEABLE(makeString(64 * 1024)), + BOOT_IMAGE(java.util.jar.JarFile.MANIFEST_NAME); + + private final String mValue; + + StringLengths(String s) { + this.mValue = s; + } + } + + private static String makeString(int length) { + final String sequence8 = "abcdefghijklmnop"; + final int numAppends = (length / 16) - 1; + StringBuilder stringBuilder = new StringBuilder(length); + + // (n-1) occurrences of "abcdefghijklmnop" + for (int i = 0; i < numAppends; ++i) { + stringBuilder.append(sequence8); + } + + // and one final occurrence of qrstuvwx. + stringBuilder.append("qrstuvwx"); + + return stringBuilder.toString(); + } + + @Parameters(name = "mStringLengths={0}") + public static Collection data() { + return Arrays.asList( + new Object[][] { + {StringLengths.BOOT_IMAGE}, + {StringLengths.EMPTY}, + {StringLengths.MOVEABLE_16}, + {StringLengths.MOVEABLE_256}, + {StringLengths.MOVEABLE_1024}, + {StringLengths.NON_MOVEABLE} + }); + } + + @Parameterized.Parameter(0) + public StringLengths mStringLengths; + + @Test + public void timeReplaceAllTrivialPatternNonExistent() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.replaceAll("fish", "0"); + } + } + + @Test + public void timeReplaceTrivialPatternAllRepeated() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.replaceAll("jklm", "0"); + } + } + + @Test + public void timeReplaceAllTrivialPatternSingleOccurrence() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.replaceAll("qrst", "0"); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringReplacePerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringReplacePerfTest.java new file mode 100644 index 000000000000..d2e657a78608 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/StringReplacePerfTest.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * 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. + */ + +package android.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.Arrays; +import java.util.Collection; + +@RunWith(Parameterized.class) +@LargeTest +public class StringReplacePerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + enum StringLengths { + EMPTY(""), + L_16(makeString(16)), + L_64(makeString(64)), + L_256(makeString(256)), + L_512(makeString(512)); + + private final String mValue; + + StringLengths(String s) { + this.mValue = s; + } + } + + private static String makeString(int length) { + final String sequence8 = "abcdefghijklmnop"; + final int numAppends = (length / 16) - 1; + StringBuilder stringBuilder = new StringBuilder(length); + + // (n-1) occurrences of "abcdefghijklmnop" + for (int i = 0; i < numAppends; ++i) { + stringBuilder.append(sequence8); + } + + // and one final occurrence of qrstuvwx. + stringBuilder.append("qrstuvwx"); + + return stringBuilder.toString(); + } + + @Parameters(name = "mStringLengths={0}") + public static Collection data() { + return Arrays.asList( + new Object[][] { + {StringLengths.EMPTY}, + {StringLengths.L_16}, + {StringLengths.L_64}, + {StringLengths.L_256}, + {StringLengths.L_512} + }); + } + + @Parameterized.Parameter(0) + public StringLengths mStringLengths; + + @Test + public void timeReplaceCharNonExistent() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.replace('z', '0'); + } + } + + @Test + public void timeReplaceCharRepeated() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.replace('a', '0'); + } + } + + @Test + public void timeReplaceSingleChar() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.replace('q', '0'); + } + } + + @Test + public void timeReplaceSequenceNonExistent() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.replace("fish", "0"); + } + } + + @Test + public void timeReplaceSequenceRepeated() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.replace("jklm", "0"); + } + } + + @Test + public void timeReplaceSingleSequence() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.replace("qrst", "0"); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringSplitPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringSplitPerfTest.java new file mode 100644 index 000000000000..2bb25ac56694 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/StringSplitPerfTest.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * 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. + */ + +package android.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.regex.Pattern; + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class StringSplitPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Test + public void timeStringSplitComma() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + "this,is,a,simple,example".split(","); + } + } + + @Test + public void timeStringSplitLiteralDot() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + "this.is.a.simple.example".split("\\."); + } + } + + @Test + public void timeStringSplitNewline() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + "this\nis\na\nsimple\nexample\n".split("\n"); + } + } + + @Test + public void timePatternSplitComma() { + Pattern p = Pattern.compile(","); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + p.split("this,is,a,simple,example"); + } + } + + @Test + public void timePatternSplitLiteralDot() { + Pattern p = Pattern.compile("\\."); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + p.split("this.is.a.simple.example"); + } + } + + @Test + public void timeStringSplitHard() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + "this,is,a,harder,example".split("[,]"); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringToBytesPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringToBytesPerfTest.java new file mode 100644 index 000000000000..1efc188f4e4d --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/StringToBytesPerfTest.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * 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. + */ + +package android.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collection; + +@RunWith(Parameterized.class) +@LargeTest +public class StringToBytesPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + enum StringLengths { + EMPTY(""), + L_16(makeString(16)), + L_64(makeString(64)), + L_256(makeString(256)), + L_512(makeString(512)), + A_16(makeAsciiString(16)), + A_64(makeAsciiString(64)), + A_256(makeAsciiString(256)), + A_512(makeAsciiString(512)); + + private final String mValue; + + StringLengths(String s) { + this.mValue = s; + } + } + + @Parameters(name = "mStringLengths={0}") + public static Collection data() { + return Arrays.asList( + new Object[][] { + {StringLengths.EMPTY}, + {StringLengths.L_16}, + {StringLengths.L_64}, + {StringLengths.L_256}, + {StringLengths.L_512}, + {StringLengths.A_16}, + {StringLengths.A_64}, + {StringLengths.A_256}, + {StringLengths.A_512} + }); + } + + @Parameterized.Parameter(0) + public StringLengths mStringLengths; + + private static String makeString(int length) { + char[] chars = new char[length]; + for (int i = 0; i < length; ++i) { + chars[i] = (char) i; + } + return new String(chars); + } + + private static String makeAsciiString(int length) { + char[] chars = new char[length]; + for (int i = 0; i < length; ++i) { + chars[i] = ((i & 0x7f) != 0) ? (char) (i & 0x7f) : '?'; + } + return new String(chars); + } + + @Test + public void timeGetBytesUtf8() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.getBytes(StandardCharsets.UTF_8); + } + } + + @Test + public void timeGetBytesIso88591() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.getBytes(StandardCharsets.ISO_8859_1); + } + } + + @Test + public void timeGetBytesAscii() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + mStringLengths.mValue.getBytes(StandardCharsets.US_ASCII); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringToRealPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringToRealPerfTest.java new file mode 100644 index 000000000000..b01948aa2255 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/StringToRealPerfTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * 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. + */ + +package android.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.Arrays; +import java.util.Collection; + +@RunWith(Parameterized.class) +@LargeTest +public class StringToRealPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Parameters(name = "mString={0}") + public static Collection data() { + return Arrays.asList( + new Object[][] { + {"NaN"}, + {"-1"}, + {"0"}, + {"1"}, + {"1.2"}, + {"-123.45"}, + {"-123.45e8"}, + {"-123.45e36"} + }); + } + + @Parameterized.Parameter(0) + public String mString; + + @Test + public void timeFloat_parseFloat() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + Float.parseFloat(mString); + } + } + + @Test + public void timeDouble_parseDouble() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + Double.parseDouble(mString); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/ThreadLocalPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/ThreadLocalPerfTest.java new file mode 100644 index 000000000000..f2565550c6c5 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/ThreadLocalPerfTest.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * 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. + */ + +package android.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class ThreadLocalPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + private static final ThreadLocal BUFFER = + new ThreadLocal() { + @Override + protected char[] initialValue() { + return new char[20]; + } + }; + + @Test + public void timeThreadLocal_get() { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + BUFFER.get(); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/TimeZonePerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/TimeZonePerfTest.java new file mode 100644 index 000000000000..8274512e1501 --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/TimeZonePerfTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * 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. + */ + +package android.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.TimeZone; + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class TimeZonePerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Test + public void timeTimeZone_getDefault() throws Exception { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + TimeZone.getDefault(); + } + } + + @Test + public void timeTimeZone_getTimeZoneUTC() throws Exception { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + TimeZone.getTimeZone("UTC"); + } + } + + @Test + public void timeTimeZone_getTimeZone_default() throws Exception { + String defaultId = TimeZone.getDefault().getID(); + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + TimeZone.getTimeZone(defaultId); + } + } + + // A time zone with relatively few transitions. + @Test + public void timeTimeZone_getTimeZone_America_Caracas() throws Exception { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + TimeZone.getTimeZone("America/Caracas"); + } + } + + // A time zone with a lot of transitions. + @Test + public void timeTimeZone_getTimeZone_America_Santiago() throws Exception { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + TimeZone.getTimeZone("America/Santiago"); + } + } + + @Test + public void timeTimeZone_getTimeZone_GMT_plus_10() throws Exception { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + TimeZone.getTimeZone("GMT+10"); + } + } +} diff --git a/apct-tests/perftests/core/src/android/libcore/regression/XMLEntitiesPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/XMLEntitiesPerfTest.java new file mode 100644 index 000000000000..2ea834d0b71c --- /dev/null +++ b/apct-tests/perftests/core/src/android/libcore/regression/XMLEntitiesPerfTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * 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. + */ + +package android.libcore.regression; + +import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; +import android.test.suitebuilder.annotation.LargeTest; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; +import org.xml.sax.InputSource; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserFactory; + +import java.io.StringReader; +import java.util.Arrays; +import java.util.Collection; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +// http://code.google.com/p/android/issues/detail?id=18102 +@RunWith(Parameterized.class) +@LargeTest +public final class XMLEntitiesPerfTest { + @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); + + @Parameters(name = "mLength={0}, mEntityFraction={1}") + public static Collection data() { + return Arrays.asList( + new Object[][] { + {10, 0}, + {10, 0.5f}, + {10, 1.0f}, + {100, 0}, + {100, 0.5f}, + {100, 1.0f}, + {1000, 0}, + {1000, 0.5f}, + {1000, 1.0f} + }); + } + + @Parameterized.Parameter(0) + public int mLength; + + @Parameterized.Parameter(1) + public float mEntityFraction; + + private XmlPullParserFactory mXmlPullParserFactory; + private DocumentBuilderFactory mDocumentBuilderFactory; + + /** a string like {@code &&++}. */ + private String mXml; + + @Before + public void setUp() throws Exception { + mXmlPullParserFactory = XmlPullParserFactory.newInstance(); + mDocumentBuilderFactory = DocumentBuilderFactory.newInstance(); + + StringBuilder xmlBuilder = new StringBuilder(); + xmlBuilder.append(""); + for (int i = 0; i < (mLength * mEntityFraction); i++) { + xmlBuilder.append("&"); + } + while (xmlBuilder.length() < mLength) { + xmlBuilder.append("+"); + } + xmlBuilder.append(""); + mXml = xmlBuilder.toString(); + } + + @Test + public void timeXmlParser() throws Exception { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + XmlPullParser parser = mXmlPullParserFactory.newPullParser(); + parser.setInput(new StringReader(mXml)); + while (parser.next() != XmlPullParser.END_DOCUMENT) { + // Keep running + } + } + } + + @Test + public void timeDocumentBuilder() throws Exception { + BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + DocumentBuilder documentBuilder = mDocumentBuilderFactory.newDocumentBuilder(); + documentBuilder.parse(new InputSource(new StringReader(mXml))); + } + } +}