summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiakai Zhang <jiakaiz@google.com>2023-05-15 12:52:41 +0100
committerJiakai Zhang <jiakaiz@google.com>2023-05-22 00:35:55 +0100
commit821266fd404a681eae31c603de9c612016944f9a (patch)
treec9181d304dceda723ae91fac574c710994089371
parent33ec06277348ecdc0036b5234e05e9dd2a385196 (diff)
downloadart-821266fd404a681eae31c603de9c612016944f9a.tar.gz
Check whether the APK has code before recording JIT profile information.
In the past, Package Manager created empty profile files for APKs that have code, and the runtime did a file existence check (removed by aosp/2407152). With ART Service, no empty profile files are created, so we have no clue whether the APK has code or not. After this change, the runtime opens the APK to check whether the APK has code or not. This change prevents the runtime from writing bootclasspath profiling info to profile files for APKs that have no code. Such files are not suitable for bootclasspath profiling because ART Service has a file GC that cleans them up during daily bg dexopt. This change admittedly makes `Runtime::RegisterAppInfo` slower because it takes some time to open the APK, but in practice, it's okay because Framework creates a classloader for the APK right after calling `Runtime::RegisterAppInfo`, which also involves opening the APK, and that open will be faster after this change. Bug: 282191456 Test: art/test.py -b --host -r -t 595-profile-saving (cherry picked from https://android-review.googlesource.com/q/commit:1e023a12fe510f259f7f2ca065591719172f3628) Merged-In: If6ed139dcb7993402ded60a3bbd8fc0530a9c20e Change-Id: If6ed139dcb7993402ded60a3bbd8fc0530a9c20e
-rw-r--r--runtime/runtime.cc24
-rw-r--r--test/595-profile-saving/res/art-gtest-jars-MainEmptyUncompressed.jarbin0 -> 116 bytes
-rw-r--r--test/595-profile-saving/src/Main.java36
3 files changed, 56 insertions, 4 deletions
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 69f0fbb4ec..2f5cd539cd 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -2763,6 +2763,30 @@ void Runtime::RegisterAppInfo(const std::string& package_name,
return;
}
+ // Framework calls this method for all split APKs. Ignore the calls for the ones with no dex code
+ // so that we don't unnecessarily create profiles for them or write bootclasspath profiling info
+ // to those profiles.
+ bool has_code = false;
+ for (const std::string& path : code_paths) {
+ std::string error_msg;
+ std::vector<uint32_t> checksums;
+ std::vector<std::string> dex_locations;
+ if (!ArtDexFileLoader::GetMultiDexChecksums(
+ path.c_str(), &checksums, &dex_locations, &error_msg)) {
+ LOG(WARNING) << error_msg;
+ continue;
+ }
+ if (dex_locations.size() > 0) {
+ has_code = true;
+ break;
+ }
+ }
+ if (!has_code) {
+ VLOG(profiler) << "JIT profile information will not be recorded: no dex code in '" +
+ android::base::Join(code_paths, ',') + "'.";
+ return;
+ }
+
jit_->StartProfileSaver(profile_output_filename, code_paths, ref_profile_filename);
}
diff --git a/test/595-profile-saving/res/art-gtest-jars-MainEmptyUncompressed.jar b/test/595-profile-saving/res/art-gtest-jars-MainEmptyUncompressed.jar
new file mode 100644
index 0000000000..252879f305
--- /dev/null
+++ b/test/595-profile-saving/res/art-gtest-jars-MainEmptyUncompressed.jar
Binary files differ
diff --git a/test/595-profile-saving/src/Main.java b/test/595-profile-saving/src/Main.java
index 37a8e6cbc6..31dc4d2148 100644
--- a/test/595-profile-saving/src/Main.java
+++ b/test/595-profile-saving/src/Main.java
@@ -24,9 +24,21 @@ public class Main {
System.loadLibrary(args[0]);
File file = null;
+ File file2 = null;
try {
+ // Register `file2` with an empty jar. Even though `file2` is registered before `file`, the
+ // runtime should not write bootclasspath methods to `file2`, and it should not even create
+ // `file2`.
+ file2 = createTempFile();
+ String emptyJarPath =
+ System.getenv("DEX_LOCATION") + "/res/art-gtest-jars-MainEmptyUncompressed.jar";
+ VMRuntime.registerAppInfo("test.app",
+ file2.getPath(),
+ file2.getPath(),
+ new String[] {emptyJarPath},
+ VMRuntime.CODE_PATH_TYPE_SPLIT_APK);
+
file = createTempFile();
- // String codePath = getDexBaseLocation();
String codePath = System.getenv("DEX_LOCATION") + "/595-profile-saving.jar";
VMRuntime.registerAppInfo("test.app",
file.getPath(),
@@ -39,9 +51,10 @@ public class Main {
File.class, Method.class);
testAddMethodToProfile(file, appMethod);
- // Delete the file to check that the runtime can save the profile even if the file doesn't
- // exist.
+ // Delete the files so that we can check if the runtime creates them. The runtime should
+ // create `file` but not `file2`.
file.delete();
+ file2.delete();
// Test that the profile saves a boot class path method with a profiling info.
Method bootMethod = File.class.getDeclaredMethod("exists");
@@ -55,11 +68,16 @@ public class Main {
Method bootNotInProfileMethod = System.class.getDeclaredMethod("console");
testMethodNotInProfile(file, bootNotInProfileMethod);
+ testProfileNotExist(file2);
+
System.out.println("IsForBootImage: " + isForBootImage(file.getPath()));
} finally {
if (file != null) {
file.delete();
}
+ if (file2 != null) {
+ file2.delete();
+ }
}
}
@@ -83,6 +101,15 @@ public class Main {
}
}
+ static void testProfileNotExist(File file) {
+ // Make sure the profile saving has been attempted.
+ ensureProfileProcessing();
+ // Verify that the profile does not exist.
+ if (file.exists()) {
+ throw new RuntimeException("Did not expect " + file + " to exist");
+ }
+ }
+
// Ensure a method has a profiling info.
public static native void ensureProfilingInfo(Method method);
// Ensures the profile saver does its usual processing.
@@ -113,7 +140,8 @@ public class Main {
}
private static class VMRuntime {
- public static final int CODE_PATH_TYPE_PRIMARY_APK = 1;
+ public static final int CODE_PATH_TYPE_PRIMARY_APK = 1 << 0;
+ public static final int CODE_PATH_TYPE_SPLIT_APK = 1 << 1;
private static final Method registerAppInfoMethod;
static {