Merge "Final set of libcore benchmarks." am: 7ec1c694b5 am: 069963bf3b am: 0ee415f589 am: f129e7b7c2
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2122613
Change-Id: Ic164c445f9367b3d890c4379b3bbbd8b9fc876bd
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/apct-tests/perftests/core/Android.bp b/apct-tests/perftests/core/Android.bp
index 2182f0b..23464f8 100644
--- a/apct-tests/perftests/core/Android.bp
+++ b/apct-tests/perftests/core/Android.bp
@@ -43,12 +43,13 @@
"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 0000000..5ad5eea
--- /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<Object[]> 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 0000000..694d609
--- /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 0000000..bdbbcb0
--- /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 0000000..42dc581
--- /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<Object[]> 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 0000000..1ec22d2
--- /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<Integer> object = new ArrayList<Integer>();
+ for (int i = 0; i < 256; ++i) {
+ object.add(i);
+ }
+ readSingleObject(object);
+ }
+
+ @Test
+ public void timeWriteArrayListInteger() throws Exception {
+ ArrayList<Integer> object = new ArrayList<Integer>();
+ 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 0000000..a1899b9
--- /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<Object[]> 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<String, KeyPair> sKeyPairs = new HashMap<String, KeyPair>();
+ private static Map<String, byte[]> sSignatures = new HashMap<String, byte[]>();
+
+ 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 0000000..c25b0ce
--- /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 0000000..eeccb5b
--- /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 0000000..34fb88b
--- /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<Object[]> 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 0000000..6854c0d
--- /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 0000000..79ff646
--- /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 0000000..8dbf9f5
--- /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 0000000..02194b1
--- /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<Object[]> 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 0000000..b0d1ee4
--- /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<Object[]> 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 0000000..d2e657a
--- /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<Object[]> 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 0000000..2bb25ac
--- /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 0000000..1efc188
--- /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<Object[]> 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 0000000..b01948a
--- /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<Object[]> 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 0000000..f256555
--- /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<char[]> BUFFER =
+ new ThreadLocal<char[]>() {
+ @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 0000000..8274512
--- /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 0000000..2ea834d
--- /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<Object[]> 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 <doc>&&++</doc>}. */
+ private String mXml;
+
+ @Before
+ public void setUp() throws Exception {
+ mXmlPullParserFactory = XmlPullParserFactory.newInstance();
+ mDocumentBuilderFactory = DocumentBuilderFactory.newInstance();
+
+ StringBuilder xmlBuilder = new StringBuilder();
+ xmlBuilder.append("<doc>");
+ for (int i = 0; i < (mLength * mEntityFraction); i++) {
+ xmlBuilder.append("&");
+ }
+ while (xmlBuilder.length() < mLength) {
+ xmlBuilder.append("+");
+ }
+ xmlBuilder.append("</doc>");
+ 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)));
+ }
+ }
+}