From 1a7c82a680c380d39c9c670714f8a85c865f1785 Mon Sep 17 00:00:00 2001 From: Guojin He Date: Wed, 6 Sep 2023 09:09:49 -0700 Subject: [PATCH] introduce option of including non-hot startup methods Summary: Android on-device dexlayout optimization takes non-hot startup only methods from baseline profile and lump them together into one section LayoutType::kLayoutTypeStartupOnly. This presumably achieves better code locality and since ART does madvise on this section during dex layout, it reduces page faults during app's startup as well. see ART code for ref: https://fburl.com/androiddexlayout Reviewed By: NTillmann Differential Revision: D48794443 fbshipit-source-id: bdcbd25c1d383506569724d21f3d8e60f304c37a --- .../ArtProfileWriterPass.cpp | 22 ++++++++++++++++--- opt/art-profile-writer/ArtProfileWriterPass.h | 12 +++++++--- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/opt/art-profile-writer/ArtProfileWriterPass.cpp b/opt/art-profile-writer/ArtProfileWriterPass.cpp index c48363d431..688100997e 100644 --- a/opt/art-profile-writer/ArtProfileWriterPass.cpp +++ b/opt/art-profile-writer/ArtProfileWriterPass.cpp @@ -52,8 +52,15 @@ void ArtProfileWriterPass::bind_config() { m_perf_config.call_count_threshold); bind("perf_coldstart_appear100_threshold", m_perf_config.appear100_threshold, m_perf_config.coldstart_appear100_threshold); + bind("perf_coldstart_appear100_nonhot_threshold", + m_perf_config.coldstart_appear100_threshold, + m_perf_config.coldstart_appear100_nonhot_threshold); bind("perf_interactions", m_perf_config.interactions, m_perf_config.interactions); + after_configuration([this] { + always_assert(m_perf_config.coldstart_appear100_nonhot_threshold < + m_perf_config.coldstart_appear100_threshold); + }); } void ArtProfileWriterPass::run_pass(DexStoresVector& stores, @@ -65,18 +72,27 @@ void ArtProfileWriterPass::run_pass(DexStoresVector& stores, bool startup = interaction_id == "ColdStart"; const auto& method_stats = method_profiles.method_stats(interaction_id); for (auto&& [method, stat] : method_stats) { + // for startup interaction, we can include it into baseline profile + // as non hot method if the method appear100 is above nonhot_threshold if (stat.appear_percent >= - (startup ? m_perf_config.coldstart_appear100_threshold + (startup ? m_perf_config.coldstart_appear100_nonhot_threshold : m_perf_config.appear100_threshold) && stat.call_count >= m_perf_config.call_count_threshold) { auto& mf = method_flags[method]; - mf.hot = true; + mf.hot = startup ? stat.appear_percent > + m_perf_config.coldstart_appear100_threshold + : true; if (startup) { // consistent with buck python config in the post-process baseline // profile generator, which is set both flags true for ColdStart // methods mf.startup = true; - mf.not_startup = true; + // if startup method is not hot, we do not set its not_startup flag + // the method still has a change to get it set if it appears in other + // interactions' hot list. Remember, ART only uses this flag to guide + // dexlayout decision, so we don't have to be pedantic to assume it + // never gets exectued post startup + mf.not_startup = mf.hot; } else { mf.not_startup = true; } diff --git a/opt/art-profile-writer/ArtProfileWriterPass.h b/opt/art-profile-writer/ArtProfileWriterPass.h index 5a1fcd78af..266f233859 100644 --- a/opt/art-profile-writer/ArtProfileWriterPass.h +++ b/opt/art-profile-writer/ArtProfileWriterPass.h @@ -26,16 +26,22 @@ class ArtProfileWriterPass : public Pass { float appear100_threshold; float call_count_threshold; float coldstart_appear100_threshold; + // Threshold to include a coldstart method in the profile, + // but not as a hot method. This threshold must be lower than + // coldstart_appear100_threshold. + float coldstart_appear100_nonhot_threshold; std::vector interactions{"ColdStart"}; PerfConfig() : appear100_threshold(101.0), call_count_threshold(0), - coldstart_appear100_threshold(80.0) {} // Default: off - PerfConfig(float a, float c, float ca) + coldstart_appear100_threshold(80.0), + coldstart_appear100_nonhot_threshold(50.0) {} // Default: off + PerfConfig(float a, float c, float ca, float can) : appear100_threshold(a), call_count_threshold(c), - coldstart_appear100_threshold(ca) {} + coldstart_appear100_threshold(ca), + coldstart_appear100_nonhot_threshold(can) {} }; PerfConfig m_perf_config;