// Returns the type descriptor of the given reference. static std::string_view GetTypeDescriptorView(const TypeReference& ref) { const dex::TypeId& type_id = ref.dex_file->GetTypeId(ref.TypeIndex()); return ref.dex_file->GetTypeDescriptorView(type_id);
}
// Returns the method representation used in the text format of the boot image profile. static std::string BootImageRepresentation(const MethodReference& ref) { const DexFile* dex_file = ref.dex_file; const dex::MethodId& id = ref.GetMethodId();
std::string signature_string(dex_file->GetMethodSignature(id).ToString());
std::string type_string(dex_file->GetTypeDescriptorView(dex_file->GetTypeId(id.class_idx_)));
std::string method_name(dex_file->GetMethodNameView(id)); return type_string +
kMethodSep +
method_name +
signature_string;
}
// Returns the class representation used in the text format of the boot image profile. static std::string BootImageRepresentation(const TypeReference& ref) { return std::string(GetTypeDescriptorView(ref));
}
// Returns the class representation used in preloaded classes. static std::string PreloadedClassesRepresentation(const TypeReference& ref) {
std::string_view descriptor = GetTypeDescriptorView(ref); return DescriptorToDot(descriptor);
}
// Formats the list of packages from the item metadata as a debug string. static std::string GetPackageUseString(const FlattenProfileData::ItemMetadata& metadata) {
std::string result; for (constauto& it : metadata.GetAnnotations()) {
result += it.GetOriginPackageName() + ",";
}
return metadata.GetAnnotations().empty()
? result
: result.substr(0, result.size() - 1);
}
// Converts a method representation to its final profile format. static std::string MethodToProfileFormat( const std::string& method, const FlattenProfileData::ItemMetadata& metadata, bool output_package_use) {
std::string flags_string; if (metadata.HasFlagSet(Hotness::kFlagHot)) {
flags_string += kMethodFlagStringHot;
} if (metadata.HasFlagSet(Hotness::kFlagStartup)) {
flags_string += kMethodFlagStringStartup;
} if (metadata.HasFlagSet(Hotness::kFlagPostStartup)) {
flags_string += kMethodFlagStringPostStartup;
}
std::string extra; if (output_package_use) {
extra = kPackageUseDelim + GetPackageUseString(metadata);
}
// Converts a class representation to its final profile or preloaded classes format. static std::string ClassToProfileFormat( const std::string& classString, const FlattenProfileData::ItemMetadata& metadata, bool output_package_use) {
std::string extra; if (output_package_use) {
extra = kPackageUseDelim + GetPackageUseString(metadata);
}
return classString + extra;
}
// Tries to asses if the given type reference is a clean class. staticbool MaybeIsClassClean(const TypeReference& ref) { const dex::ClassDef* class_def = ref.dex_file->FindClassDef(ref.TypeIndex()); if (class_def == nullptr) { returnfalse;
}
ClassAccessor accessor(*ref.dex_file, *class_def); for (auto& it : accessor.GetStaticFields()) { if (!it.IsFinal()) { // Not final static field will probably dirty the class. returnfalse;
}
} for (auto& it : accessor.GetMethods()) {
uint32_t flags = it.GetAccessFlags(); if ((flags & kAccNative) != 0) { // Native method will get dirtied. returnfalse;
} if ((flags & kAccConstructor) != 0 && (flags & kAccStatic) != 0) { // Class initializer, may get dirtied (not sure). returnfalse;
}
}
returntrue;
}
// Returns true iff the item should be included in the profile. // (i.e. it passes the given aggregation thresholds) staticbool IncludeItemInProfile(uint32_t max_aggregation_count,
uint32_t item_threshold, const FlattenProfileData::ItemMetadata& metadata, const BootImageOptions& options) {
CHECK_NE(max_aggregation_count, 0u); float item_percent = metadata.GetAnnotations().size() / static_cast<float>(max_aggregation_count); for (constauto& annotIt : metadata.GetAnnotations()) { constauto&thresholdIt =
options.special_packages_thresholds.find(annotIt.GetOriginPackageName()); if (thresholdIt != options.special_packages_thresholds.end()) { if (item_percent >= (thresholdIt->second / 100.f)) { returntrue;
}
}
} return item_percent >= (item_threshold / 100.f);
}
// Returns true iff a method with the given metada should be included in the profile. staticbool IncludeMethodInProfile(uint32_t max_aggregation_count, const FlattenProfileData::ItemMetadata& metadata, const BootImageOptions& options) { return IncludeItemInProfile(max_aggregation_count, options.method_threshold, metadata, options);
}
// Returns true iff a class with the given metada should be included in the profile. staticbool IncludeClassInProfile(const TypeReference& type_ref,
uint32_t max_aggregation_count, const FlattenProfileData::ItemMetadata& metadata, const BootImageOptions& options) {
uint32_t threshold = MaybeIsClassClean(type_ref)
? options.image_class_clean_threshold
: options.image_class_threshold; return IncludeItemInProfile(max_aggregation_count, threshold, metadata, options);
}
// Returns true iff a class with the given metada should be included in the list of // prelaoded classes. staticbool IncludeInPreloadedClasses(const std::string& class_name,
uint32_t max_aggregation_count, const FlattenProfileData::ItemMetadata& metadata, const BootImageOptions& options) { bool denylisted = options.preloaded_classes_denylist.find(class_name) !=
options.preloaded_classes_denylist.end(); return !denylisted && IncludeItemInProfile(
max_aggregation_count, options.preloaded_class_threshold, metadata, options);
}
std::unique_ptr<FlattenProfileData> flattend_data(new FlattenProfileData()); for (const std::string& profile_file : profile_files) {
ProfileCompilationInfo profile(/*for_boot_image=*/ true); if (!profile.Load(profile_file, /*clear_if_invalid=*/ false)) {
LOG(ERROR) << "Profile is not a valid: " << profile_file; returnfalse;
}
std::unique_ptr<FlattenProfileData> currentData = profile.ExtractProfileData(dex_files);
flattend_data->MergeData(*currentData);
}
// We want the output sorted by the method/class name. // So we use an intermediate map for that. // There's no attempt to optimize this as it's not part of any critical path, // and mostly executed on hosts.
SafeMap<std::string, FlattenProfileData::ItemMetadata> profile_methods;
SafeMap<std::string, FlattenProfileData::ItemMetadata> profile_classes;
SafeMap<std::string, FlattenProfileData::ItemMetadata> preloaded_classes;
for (constauto& it : flattend_data->GetMethodData()) { if (IncludeMethodInProfile(flattend_data->GetMaxAggregationForMethods(), it.second, options)) {
FlattenProfileData::ItemMetadata metadata(it.second); if (options.upgrade_startup_to_hot
&& ((metadata.GetFlags() & Hotness::Flag::kFlagStartup) != 0)) {
metadata.AddFlag(Hotness::Flag::kFlagHot);
}
profile_methods.Put(BootImageRepresentation(it.first), metadata);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.