ART: Faster PrettyMethod().
Rewrite DexFile::PrettyMethod() to avoid copying strings.
This improves the performance, especially when requesting
the signature.
Avoid code duplication in ArtMethod::PrettyMethod() and
delegate to DexFile::PrettyMethod().
10 million invocations of ArtMethod/DexFile::PrettyMethod()
for "void Main.main(java.lang.String[] args)" with (+) or
without (-) signature, time in ms:
host/32-bit host/64-bit angler/32-bit angler/64-bit
AM+: 10407-> 5020 6374-> 3302 32413->13140 17558->10003
DF+: 7280-> 4259 3881-> 2828 19287-> 9331 10343-> 7375
AM-: 2682-> 1599 2025-> 1186 7206-> 4271 7447-> 4166
DF-: 861-> 871 653-> 640 1574-> 1430 1828-> 1712
Test: m test-art-host-gtest
Test: testrunner.py --host
Change-Id: Ifb79abe1a7f4fc6adc10a34f5d49dc6681d06699
diff --git a/runtime/dex_file_test.cc b/runtime/dex_file_test.cc
index 1a73062..a7bf59e 100644
--- a/runtime/dex_file_test.cc
+++ b/runtime/dex_file_test.cc
@@ -423,28 +423,83 @@
ASSERT_EQ("()V", signature);
}
- // Check both virtual methods.
- ASSERT_EQ(2U, it.NumVirtualMethods());
- {
+ // Check all virtual methods.
+ struct Result {
+ const char* name;
+ const char* signature;
+ const char* pretty_method;
+ };
+ static const Result results[] = {
+ {
+ "m1",
+ "(IDJLjava/lang/Object;)Ljava/lang/Float;",
+ "java.lang.Float GetMethodSignature.m1(int, double, long, java.lang.Object)"
+ },
+ { // NOLINT [whitespace/braces] [4]
+ "m2",
+ "(ZSC)LGetMethodSignature;",
+ "GetMethodSignature GetMethodSignature.m2(boolean, short, char)"
+ },
+ { // NOLINT [whitespace/braces] [4]
+ "m3",
+ "()V",
+ "void GetMethodSignature.m3()"
+ },
+ { // NOLINT [whitespace/braces] [4]
+ "m4",
+ "(I)V",
+ "void GetMethodSignature.m4(int)"
+ },
+ { // NOLINT [whitespace/braces] [4]
+ "m5",
+ "(II)V",
+ "void GetMethodSignature.m5(int, int)"
+ },
+ { // NOLINT [whitespace/braces] [4]
+ "m6",
+ "(II[[I)V",
+ "void GetMethodSignature.m6(int, int, int[][])"
+ },
+ { // NOLINT [whitespace/braces] [4]
+ "m7",
+ "(II[[ILjava/lang/Object;)V",
+ "void GetMethodSignature.m7(int, int, int[][], java.lang.Object)"
+ },
+ { // NOLINT [whitespace/braces] [4]
+ "m8",
+ "(II[[ILjava/lang/Object;[[Ljava/lang/Object;)V",
+ "void GetMethodSignature.m8(int, int, int[][], java.lang.Object, java.lang.Object[][])"
+ },
+ { // NOLINT [whitespace/braces] [4]
+ "m9",
+ "()I",
+ "int GetMethodSignature.m9()"
+ },
+ { // NOLINT [whitespace/braces] [4]
+ "mA",
+ "()[[I",
+ "int[][] GetMethodSignature.mA()"
+ },
+ { // NOLINT [whitespace/braces] [4]
+ "mB",
+ "()[[Ljava/lang/Object;",
+ "java.lang.Object[][] GetMethodSignature.mB()"
+ },
+ };
+ ASSERT_EQ(arraysize(results), it.NumVirtualMethods());
+ for (const Result& r : results) {
it.Next();
const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
const char* name = raw->StringDataByIdx(method_id.name_idx_);
- ASSERT_STREQ("m1", name);
+ ASSERT_STREQ(r.name, name);
std::string signature(raw->GetMethodSignature(method_id).ToString());
- ASSERT_EQ("(IDJLjava/lang/Object;)Ljava/lang/Float;", signature);
- }
+ ASSERT_EQ(r.signature, signature);
- {
- it.Next();
- const DexFile::MethodId& method_id = raw->GetMethodId(it.GetMemberIndex());
-
- const char* name = raw->StringDataByIdx(method_id.name_idx_);
- ASSERT_STREQ("m2", name);
-
- std::string signature(raw->GetMethodSignature(method_id).ToString());
- ASSERT_EQ("(ZSC)LGetMethodSignature;", signature);
+ std::string plain_method = std::string("GetMethodSignature.") + r.name;
+ ASSERT_EQ(plain_method, raw->PrettyMethod(it.GetMemberIndex(), /* with_signature */ false));
+ ASSERT_EQ(r.pretty_method, raw->PrettyMethod(it.GetMemberIndex(), /* with_signature */ true));
}
}