Skip to content

Commit

Permalink
add MergeabilityAwareInterDexReshufflePass
Browse files Browse the repository at this point in the history
Reviewed By: thezhangwei, beicy

Differential Revision: D56172431

fbshipit-source-id: 989888169622811e23c95bce9bf0e3cd4a00aca5
  • Loading branch information
ShatianWang authored and facebook-github-bot committed Apr 17, 2024
1 parent 7b5efcb commit aadecc3
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 44 deletions.
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@ libopt_la_SOURCES = \
opt/interdex/InterDexPass.cpp \
opt/interdex/InterDexReshuffleImpl.cpp \
opt/interdex/InterDexReshufflePass.cpp \
opt/interdex/MAInterDexReshufflePass.cpp \
opt/interdex/SortRemainingClassesPass.cpp \
opt/kotlin-lambda/RewriteKotlinSingletonInstance.cpp \
opt/kotlin-lambda/KotlinObjectInliner.cpp \
Expand Down
2 changes: 1 addition & 1 deletion opt/class-merging/IntraDexClassMergingPass.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class IntraDexClassMergingPass : public Pass {
using namespace redex_properties::interactions;
using namespace redex_properties::names;
return {
{DexLimitsObeyed, Preserves},
{DexLimitsObeyed, Establishes},
{NoResolvablePureRefs, Preserves},
{InitialRenameClass, Preserves},
};
Expand Down
30 changes: 3 additions & 27 deletions opt/interdex/InterDexReshufflePass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@
*/

#include "InterDexReshufflePass.h"
#include "ClassMerging.h"
#include "ConfigFiles.h"
#include "DedupStrings.h"
#include "DexClass.h"
#include "DexStructure.h"
#include "DexUtil.h"
#include "InterDexPass.h"
#include "ModelSpecGenerator.h"
#include "PassManager.h"
#include "Show.h"
#include "StlUtil.h"
Expand Down Expand Up @@ -51,29 +49,9 @@ void InterDexReshufflePass::run_pass(DexStoresVector& stores,
return;
}

auto has_IDCM_pass = mgr.find_pass("IntraDexClassMergingPass");
// The mergeability_aware reshuffle algorithm is only enabled when 1) there
// will be a IDCM pass; 2) m_allow_mergeability_aware is set true; and 3) This
// is the first run of InterDexReshufflePass.
bool enable_mergeability_aware_reshuffle =
has_IDCM_pass && m_allow_mergeability_aware && m_run == 0;
if (enable_mergeability_aware_reshuffle) {
TRACE(PM, 1, "Run regular mergeability-aware InterDexReshuffle");
mgr.incr_metric("Mergeability_aware", 1);
class_merging::Model merging_model = class_merging::construct_global_model(
original_scope, mgr, conf, stores);

InterDexReshuffleImpl impl(conf, mgr, m_config, original_scope, root_dexen,
merging_model);
impl.compute_plan();
impl.apply_plan();
} else {
TRACE(PM, 1, "Run regular InterDexReshuffle");
mgr.incr_metric("Mergeability_aware", 0);
InterDexReshuffleImpl impl(conf, mgr, m_config, original_scope, root_dexen);
impl.compute_plan();
impl.apply_plan();
}
InterDexReshuffleImpl impl(conf, mgr, m_config, original_scope, root_dexen);
impl.compute_plan();
impl.apply_plan();

// Sanity check
std::unordered_set<DexClass*> original_scope_set(original_scope.begin(),
Expand All @@ -85,8 +63,6 @@ void InterDexReshufflePass::run_pass(DexStoresVector& stores,
for (auto cls : original_scope_set) {
always_assert(new_scope_set.count(cls));
}

++m_run;
}

static InterDexReshufflePass s_pass;
16 changes: 0 additions & 16 deletions opt/interdex/InterDexReshufflePass.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,30 +89,14 @@ class InterDexReshufflePass : public Pass {
m_config.max_batch_size,
"How many class to move per batch. More might yield better results, "
"but might take longer.");
bind("other_weight",
m_config.other_weight,
m_config.other_weight,
"Weight for non-deduped method in mergeability-aware reshuffle cost "
"function.");
bind("deduped_weight",
m_config.deduped_weight,
m_config.deduped_weight,
"Weight for deduped method in mergeability-aware reshuffle cost "
"function.");
bind("exclude_below20pct_coldstart_classes",
false,
m_config.exclude_below20pct_coldstart_classes,
"Whether to exclude coldstart classes in between 1pctColdStart and "
"20pctColdStart marker"
"from the reshuffle.");
bind("allow_mergeability_aware", true, m_allow_mergeability_aware);
}

private:
ReshuffleConfig m_config;

// Which iteration of `run_pass`.
size_t m_run{0};

bool m_allow_mergeability_aware;
};
82 changes: 82 additions & 0 deletions opt/interdex/MAInterDexReshufflePass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#include "MAInterDexReshufflePass.h"
#include "ClassMerging.h"
#include "ConfigFiles.h"
#include "DedupStrings.h"
#include "DexClass.h"
#include "DexStructure.h"
#include "DexUtil.h"
#include "InterDexPass.h"
#include "ModelSpecGenerator.h"
#include "PassManager.h"
#include "Show.h"
#include "StlUtil.h"
#include "Trace.h"
#include "Walkers.h"

namespace {
const interdex::InterDexPass* get_interdex_pass(const PassManager& mgr) {
const auto* pass =
static_cast<interdex::InterDexPass*>(mgr.find_pass("InterDexPass"));
always_assert_log(pass, "InterDexPass missing");
return pass;
}
} // namespace

void MergeabilityAwareInterDexReshufflePass::run_pass(DexStoresVector& stores,
ConfigFiles& conf,
PassManager& mgr) {
const auto* interdex_pass = get_interdex_pass(mgr);
if (!interdex_pass->minimize_cross_dex_refs()) {
mgr.incr_metric("no minimize_cross_dex_refs", 1);
TRACE(IDEXR, 1,
"MergeabilityAwareInterDexReshufflePass not run because InterDexPass "
"is not configured "
"for minimize_cross_dex_refs.");
return;
}

auto has_IDCM_pass = mgr.find_pass("IntraDexClassMergingPass");
if (!has_IDCM_pass) {
mgr.incr_metric("no IntraDexClassMergingPass", 1);
TRACE(IDEXR, 1,
"MergeabilityAwareInterDexReshufflePass not run because there is no "
"IntraDexClassMergingPass.");
return;
}
auto original_scope = build_class_scope(stores);

auto& root_store = stores.at(0);
auto& root_dexen = root_store.get_dexen();
if (root_dexen.size() == 1) {
// only a primary dex? Nothing to do
return;
}

class_merging::Model merging_model =
class_merging::construct_global_model(original_scope, mgr, conf, stores);

InterDexReshuffleImpl impl(conf, mgr, m_config, original_scope, root_dexen,
merging_model);
impl.compute_plan();
impl.apply_plan();

// Sanity check
std::unordered_set<DexClass*> original_scope_set(original_scope.begin(),
original_scope.end());
auto new_scope = build_class_scope(stores);
std::unordered_set<DexClass*> new_scope_set(new_scope.begin(),
new_scope.end());
always_assert(original_scope_set.size() == new_scope_set.size());
for (auto cls : original_scope_set) {
always_assert(new_scope_set.count(cls));
}
}

static MergeabilityAwareInterDexReshufflePass s_pass;
89 changes: 89 additions & 0 deletions opt/interdex/MAInterDexReshufflePass.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#pragma once

#include "DexClass.h"
#include "InterDex.h"
#include "InterDexReshuffleImpl.h"
#include "Pass.h"

/* Similar to InterDexReshufflePass, this pass impls Local Search Algotithm to
* minize cross-dex refs by reshuffling classes among dex files. Different from
* InterDexReshufflePass, when reshuffling classes, this pass considers the
* classes mergeability. That is, if two classes may be merged in later IDCM,
* they have the high possibility to moved to the same dex.
*/
class MergeabilityAwareInterDexReshufflePass : public Pass {
public:
explicit MergeabilityAwareInterDexReshufflePass()
: Pass("MergeabilityAwareInterDexReshufflePass") {}

redex_properties::PropertyInteractions get_property_interactions()
const override {
using namespace redex_properties::interactions;
using namespace redex_properties::names;
return {
{NoResolvablePureRefs, Preserves},
{InitialRenameClass, Preserves},
};
}

void run_pass(DexStoresVector&, ConfigFiles&, PassManager&) override;

void bind_config() override {
bind("reserved_extra_frefs",
m_config.reserved_extra_frefs,
m_config.reserved_extra_frefs,
"How many extra frefs to be reserved for the dexes this pass "
"processes.");
bind("reserved_extra_trefs",
m_config.reserved_extra_trefs,
m_config.reserved_extra_trefs,
"How many extra trefs to be reserved for the dexes this pass "
"processes.");
bind("reserved_extra_mrefs",
m_config.reserved_extra_mrefs,
m_config.reserved_extra_mrefs,
"How many extra mrefs to be reserved for the dexes this pass "
"processes.");
bind("extra_linear_alloc_limit",
m_config.extra_linear_alloc_limit,
m_config.extra_linear_alloc_limit,
"How many extra linear_alloc_limit to be reserved for the dexes "
"this pass rocesses.");
bind("max_batches",
m_config.max_batches,
m_config.max_batches,
"How many batches to execute. More might yield better results, but "
"might take longer.");
bind("max_batch_size",
m_config.max_batch_size,
m_config.max_batch_size,
"How many class to move per batch. More might yield better results, "
"but might take longer.");
bind("other_weight",
m_config.other_weight,
m_config.other_weight,
"Weight for non-deduped method in mergeability-aware reshuffle cost "
"function.");
bind("deduped_weight",
m_config.deduped_weight,
m_config.deduped_weight,
"Weight for deduped method in mergeability-aware reshuffle cost "
"function.");
bind("exclude_below20pct_coldstart_classes",
false,
m_config.exclude_below20pct_coldstart_classes,
"Whether to exclude coldstart classes in between 1pctColdStart and "
"20pctColdStart marker"
"from the reshuffle.");
}

private:
ReshuffleConfig m_config;
};

0 comments on commit aadecc3

Please sign in to comment.