Profman: Use method_percentage and class_percentage values passed for generating profiles
The percentage was only used for profiles without dex files, however, this
could also be used when the dex files are provided.
Test: manual
Change-Id: Ia8eff4231951b6531ce887938ae2eb10ea502089
diff --git a/profman/profman.cc b/profman/profman.cc
index fd3bd11..d0c99e0 100644
--- a/profman/profman.cc
+++ b/profman/profman.cc
@@ -116,9 +116,9 @@
UsageError(" --generate-test-profile=<filename>: generates a random profile file for testing.");
UsageError(" --generate-test-profile-num-dex=<number>: number of dex files that should be");
UsageError(" included in the generated profile. Defaults to 20.");
- UsageError(" --generate-test-profile-method-ratio=<number>: the percentage from the maximum");
+ UsageError(" --generate-test-profile-method-percentage=<number>: the percentage from the maximum");
UsageError(" number of methods that should be generated. Defaults to 5.");
- UsageError(" --generate-test-profile-class-ratio=<number>: the percentage from the maximum");
+ UsageError(" --generate-test-profile-class-percentage=<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.");
@@ -151,8 +151,8 @@
// Note: make sure you update the Usage if you change these values.
static constexpr uint16_t kDefaultTestProfileNumDex = 20;
-static constexpr uint16_t kDefaultTestProfileMethodRatio = 5;
-static constexpr uint16_t kDefaultTestProfileClassRatio = 5;
+static constexpr uint16_t kDefaultTestProfileMethodPercentage = 5;
+static constexpr uint16_t kDefaultTestProfileClassPercentage = 5;
// Separators used when parsing human friendly representation of profiles.
static const std::string kMethodSep = "->";
@@ -178,8 +178,8 @@
generate_boot_image_profile_(false),
dump_output_to_fd_(kInvalidFd),
test_profile_num_dex_(kDefaultTestProfileNumDex),
- test_profile_method_ratio_(kDefaultTestProfileMethodRatio),
- test_profile_class_ratio_(kDefaultTestProfileClassRatio),
+ test_profile_method_percerntage_(kDefaultTestProfileMethodPercentage),
+ test_profile_class_percentage_(kDefaultTestProfileClassPercentage),
test_profile_seed_(NanoTime()),
start_ns_(NanoTime()) {}
@@ -253,15 +253,15 @@
"--generate-test-profile-num-dex",
&test_profile_num_dex_,
Usage);
- } else if (option.starts_with("--generate-test-profile-method-ratio")) {
+ } else if (option.starts_with("--generate-test-profile-method-percentage")) {
ParseUintOption(option,
- "--generate-test-profile-method-ratio",
- &test_profile_method_ratio_,
+ "--generate-test-profile-method-percentage",
+ &test_profile_method_percerntage_,
Usage);
- } else if (option.starts_with("--generate-test-profile-class-ratio")) {
+ } else if (option.starts_with("--generate-test-profile-class-percentage")) {
ParseUintOption(option,
- "--generate-test-profile-class-ratio",
- &test_profile_class_ratio_,
+ "--generate-test-profile-class-percentage",
+ &test_profile_class_percentage_,
Usage);
} else if (option.starts_with("--generate-test-profile-seed=")) {
ParseUintOption(option, "--generate-test-profile-seed", &test_profile_seed_, Usage);
@@ -1014,11 +1014,11 @@
int GenerateTestProfile() {
// Validate parameters for this command.
- if (test_profile_method_ratio_ > 100) {
- Usage("Invalid ratio for --generate-test-profile-method-ratio");
+ if (test_profile_method_percerntage_ > 100) {
+ Usage("Invalid percentage for --generate-test-profile-method-percentage");
}
- if (test_profile_class_ratio_ > 100) {
- Usage("Invalid ratio for --generate-test-profile-class-ratio");
+ if (test_profile_class_percentage_ > 100) {
+ Usage("Invalid percentage for --generate-test-profile-class-percentage");
}
// If given APK files or DEX locations, check that they're ok.
if (!apk_files_.empty() || !apks_fd_.empty() || !dex_locations_.empty()) {
@@ -1039,8 +1039,8 @@
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_method_percerntage_,
+ test_profile_class_percentage_,
test_profile_seed_);
} else {
// Initialize MemMap for ZipArchive::OpenFromFd.
@@ -1051,6 +1051,8 @@
// Create a random profile file based on the set of dex files.
result = ProfileCompilationInfo::GenerateTestProfile(profile_test_fd,
dex_files,
+ test_profile_method_percerntage_,
+ test_profile_class_percentage_,
test_profile_seed_);
}
close(profile_test_fd); // ignore close result.
@@ -1101,8 +1103,8 @@
std::string test_profile_;
std::string create_profile_from_file_;
uint16_t test_profile_num_dex_;
- uint16_t test_profile_method_ratio_;
- uint16_t test_profile_class_ratio_;
+ uint16_t test_profile_method_percerntage_;
+ uint16_t test_profile_class_percentage_;
uint32_t test_profile_seed_;
uint64_t start_ns_;
};
diff --git a/runtime/jit/profile_compilation_info.cc b/runtime/jit/profile_compilation_info.cc
index c9bfc9c..0cbcebc 100644
--- a/runtime/jit/profile_compilation_info.cc
+++ b/runtime/jit/profile_compilation_info.cc
@@ -343,10 +343,6 @@
<< " bytes. Profile will not be written to disk.";
return false;
}
- if (required_capacity > kProfileSizeWarningThresholdInBytes) {
- LOG(WARNING) << "Profile data size exceeds "
- << std::to_string(kProfileSizeWarningThresholdInBytes);
- }
AddUintToBuffer(&buffer, required_capacity);
if (!WriteBuffer(fd, buffer.data(), buffer.size())) {
return false;
@@ -413,6 +409,11 @@
required_capacity,
&output_size);
+ if (output_size > kProfileSizeWarningThresholdInBytes) {
+ LOG(WARNING) << "Profile data size exceeds "
+ << std::to_string(kProfileSizeWarningThresholdInBytes);
+ }
+
buffer.clear();
AddUintToBuffer(&buffer, output_size);
@@ -1488,16 +1489,16 @@
// Naive implementation to generate a random profile file suitable for testing.
bool ProfileCompilationInfo::GenerateTestProfile(int fd,
uint16_t number_of_dex_files,
- uint16_t method_ratio,
- uint16_t class_ratio,
+ uint16_t method_percentage,
+ uint16_t class_percentage,
uint32_t random_seed) {
const std::string base_dex_location = "base.apk";
ProfileCompilationInfo info;
// The limits are defined by the dex specification.
const uint16_t max_method = std::numeric_limits<uint16_t>::max();
const uint16_t max_classes = std::numeric_limits<uint16_t>::max();
- uint16_t number_of_methods = max_method * method_ratio / 100;
- uint16_t number_of_classes = max_classes * class_ratio / 100;
+ uint16_t number_of_methods = max_method * method_percentage / 100;
+ uint16_t number_of_classes = max_classes * class_percentage / 100;
std::srand(random_seed);
@@ -1534,28 +1535,47 @@
}
// Naive implementation to generate a random profile file suitable for testing.
+// Description of random selection:
+// * Select a random starting point S.
+// * For every index i, add (S+i) % (N - total number of methods/classes) to profile with the
+// probably of 1/(N - i - number of methods/classes needed to add in profile).
bool ProfileCompilationInfo::GenerateTestProfile(
int fd,
std::vector<std::unique_ptr<const DexFile>>& dex_files,
+ uint16_t method_percentage,
+ uint16_t class_percentage,
uint32_t random_seed) {
std::srand(random_seed);
ProfileCompilationInfo info;
for (std::unique_ptr<const DexFile>& dex_file : dex_files) {
const std::string& location = dex_file->GetLocation();
uint32_t checksum = dex_file->GetLocationChecksum();
- for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) {
- // Randomly add a class from the dex file (with 50% chance).
- if (std::rand() % 2 != 0) {
+
+ uint32_t number_of_classes = dex_file->NumClassDefs();
+ uint32_t classes_required_in_profile = (number_of_classes * class_percentage) / 100;
+ uint32_t class_start_index = rand() % number_of_classes;
+ for (uint32_t i = 0; i < number_of_classes && classes_required_in_profile; ++i) {
+ if (number_of_classes - i == classes_required_in_profile ||
+ std::rand() % (number_of_classes - i - classes_required_in_profile) == 0) {
+ uint32_t class_index = (i + class_start_index) % number_of_classes;
info.AddClassIndex(location,
checksum,
- dex_file->GetClassDef(i).class_idx_,
+ dex_file->GetClassDef(class_index).class_idx_,
dex_file->NumMethodIds());
+ classes_required_in_profile--;
}
}
- for (uint32_t i = 0; i < dex_file->NumMethodIds(); ++i) {
- // Randomly add a method from the dex file (with 50% chance).
- if (std::rand() % 2 != 0) {
- info.AddMethodIndex(MethodHotness::kFlagHot, MethodReference(dex_file.get(), i));
+
+ uint32_t number_of_methods = dex_file->NumMethodIds();
+ uint32_t methods_required_in_profile = (number_of_methods * method_percentage) / 100;
+ uint32_t method_start_index = rand() % number_of_methods;
+ for (uint32_t i = 0; i < number_of_methods && methods_required_in_profile; ++i) {
+ if (number_of_methods - i == methods_required_in_profile ||
+ std::rand() % (number_of_methods - i - methods_required_in_profile) == 0) {
+ uint32_t method_index = (method_start_index + i) % number_of_methods;
+ info.AddMethodIndex(MethodHotness::kFlagHot, MethodReference(dex_file.get(),
+ method_index));
+ methods_required_in_profile--;
}
}
}
diff --git a/runtime/jit/profile_compilation_info.h b/runtime/jit/profile_compilation_info.h
index ffb67ae..6d1fb27 100644
--- a/runtime/jit/profile_compilation_info.h
+++ b/runtime/jit/profile_compilation_info.h
@@ -372,6 +372,8 @@
// the provided list of dex files.
static bool GenerateTestProfile(int fd,
std::vector<std::unique_ptr<const DexFile>>& dex_files,
+ uint16_t method_percentage,
+ uint16_t class_percentage,
uint32_t random_seed);
// Check that the given profile method info contain the same data.