Add profman option to generate a random profile based on dex files.
Extends --generate-test-profile to make a randomized profile based on a
set of dex files. Will randomly incorporate classes and methods from all
the dex files given. Can be given a random seed for reproducibility.
Bug: 36107940
Test: mm test-art-host-gtest-profile_assistant_test
Change-Id: Ib0e54bde5317439516a39afa41c3c9980834fa54
diff --git a/profman/profman.cc b/profman/profman.cc
index dac95b8..5504695 100644
--- a/profman/profman.cc
+++ b/profman/profman.cc
@@ -117,6 +117,8 @@
UsageError(" number of methods that should be generated. Defaults to 5.");
UsageError(" --generate-test-profile-class-ratio=<number>: the percentage from the maximum");
UsageError(" number of classes that should be generated. Defaults to 5.");
+ UsageError(" --generate-test-profile-seed=<number>: seed for random number generator used when");
+ UsageError(" generating random test profiles. Defaults to using NanoTime.");
UsageError("");
UsageError(" --create-profile-from=<filename>: creates a profile from a list of classes.");
UsageError("");
@@ -156,6 +158,7 @@
test_profile_num_dex_(kDefaultTestProfileNumDex),
test_profile_method_ratio_(kDefaultTestProfileMethodRatio),
test_profile_class_ratio_(kDefaultTestProfileClassRatio),
+ test_profile_seed_(NanoTime()),
start_ns_(NanoTime()) {}
~ProfMan() {
@@ -221,6 +224,8 @@
"--generate-test-profile-class-ratio",
&test_profile_class_ratio_,
Usage);
+ } else if (option.starts_with("--generate-test-profile-seed=")) {
+ ParseUintOption(option, "--generate-test-profile-seed", &test_profile_seed_, Usage);
} else {
Usage("Unknown argument '%s'", option.data());
}
@@ -798,17 +803,39 @@
if (test_profile_class_ratio_ > 100) {
Usage("Invalid ratio for --generate-test-profile-class-ratio");
}
+ // If given APK files or DEX locations, check that they're ok.
+ if (!apk_files_.empty() || !apks_fd_.empty() || !dex_locations_.empty()) {
+ if (apk_files_.empty() && apks_fd_.empty()) {
+ Usage("APK files must be specified when passing DEX locations to --generate-test-profile");
+ }
+ if (dex_locations_.empty()) {
+ Usage("DEX locations must be specified when passing APK files to --generate-test-profile");
+ }
+ }
// ShouldGenerateTestProfile confirms !test_profile_.empty().
int profile_test_fd = open(test_profile_.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0644);
if (profile_test_fd < 0) {
LOG(ERROR) << "Cannot open " << test_profile_ << strerror(errno);
return -1;
}
-
- bool result = ProfileCompilationInfo::GenerateTestProfile(profile_test_fd,
- test_profile_num_dex_,
- test_profile_method_ratio_,
- test_profile_class_ratio_);
+ bool result;
+ if (apk_files_.empty() && apks_fd_.empty() && dex_locations_.empty()) {
+ result = ProfileCompilationInfo::GenerateTestProfile(profile_test_fd,
+ test_profile_num_dex_,
+ test_profile_method_ratio_,
+ test_profile_class_ratio_,
+ test_profile_seed_);
+ } else {
+ // Initialize MemMap for ZipArchive::OpenFromFd.
+ MemMap::Init();
+ // Open the dex files to look up classes and methods.
+ std::vector<std::unique_ptr<const DexFile>> dex_files;
+ OpenApkFilesFromLocations(&dex_files);
+ // Create a random profile file based on the set of dex files.
+ result = ProfileCompilationInfo::GenerateTestProfile(profile_test_fd,
+ dex_files,
+ test_profile_seed_);
+ }
close(profile_test_fd); // ignore close result.
return result ? 0 : -1;
}
@@ -857,6 +884,7 @@
uint16_t test_profile_num_dex_;
uint16_t test_profile_method_ratio_;
uint16_t test_profile_class_ratio_;
+ uint32_t test_profile_seed_;
uint64_t start_ns_;
};