redex icon indicating copy to clipboard operation
redex copied to clipboard

how to config redex pass

Open 123zhangmiao opened this issue 3 years ago • 10 comments

How to configure a set of universal pass refers to the good optimization effect that can be achieved by using this set of pass Settings for different apps, how to know and avoid the potential risks of each pass, and what are the standards for measuring the optimization effect.

123zhangmiao avatar Oct 17 '22 11:10 123zhangmiao

Hi, the aggressive.config is a good starting point. Please let us know if run into issues with that. We do plan to keep the config information more updated in the future.

thezhangwei avatar Oct 17 '22 17:10 thezhangwei

Running RemoveEmptyClassesPass... RemoveEmptyClassesPass 1 (run) completed in 0.0 seconds

If I get a log like the one above, I can delete the pass RemoveEmptyClassesPass right?

The other question is, what is the basis for removing or adding pass. Looking forward to reply!

123zhangmiao avatar Oct 18 '22 09:10 123zhangmiao

If I get a log like the one above, I can delete the pass RemoveEmptyClassesPass right?

It seems like it doesn't do much but it could be input dependent. It might find empty classes to remove for some other inputs. You don't necessarily have to prune passes even if they don't seem to do much for now. It's not taking much time to run anyways, it seems.

You can always add other passes to the passes list and see what they do. Usually the default config for that pass would work. You can also run one pass multiple times by replicating it in the passes list. Hopefully that helps.

thezhangwei avatar Oct 18 '22 17:10 thezhangwei

How do I see what a pass does? What are the criteria for whether a pass is valuable?

123zhangmiao avatar Oct 19 '22 02:10 123zhangmiao

As you said, default.config is a way to make sure that every pass works, aggressive.config is a good place to start. What should I choose if I want to have a pass configuration that is universal and works for different inputs? Please answer my confusion. My requirement is to have a common pass configuration to optimize different APKs. I would also like to know the criteria to measure the effectiveness of each pass optimization, as well as the overall config optimization. After all, the optimization of redex tool is determined by configuring pass. Do you agree with me?

123zhangmiao avatar Oct 19 '22 02:10 123zhangmiao

When used aggressive.config, the following error occurs

File "/tmp/redex.TGskxX/redex.py", line 956, in prepare_redex config_dict = json.loads(remove_comments(lines)) File "/usr/local/Cellar/[email protected]/3.9.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/json/init.py", line 346, in loads return _default_decoder.decode(s) File "/usr/local/Cellar/[email protected]/3.9.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/json/decoder.py", line 337, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File "/usr/local/Cellar/[email protected]/3.9.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/json/decoder.py", line 353, in raw_decode obj, end = self.scan_once(s, idx) json.decoder.JSONDecodeError: Expecting ',' delimiter: line 21 column 7 (char 257)

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "/tmp/redex.TGskxX/redex.py", line 1262, in with_temp_cleanup(lambda: run_redex(args), args.always_clean_up) File "/private/tmp/redex.TGskxX/pyredex/utils.py", line 62, in with_temp_cleanup fn() File "/tmp/redex.TGskxX/redex.py", line 1262, in with_temp_cleanup(lambda: run_redex(args), args.always_clean_up) File "/tmp/redex.TGskxX/redex.py", line 1238, in run_redex state = prepare_redex(args) File "/tmp/redex.TGskxX/redex.py", line 958, in prepare_redex raise ValueError( ValueError: Invalid JSON in ReDex config file: redex-test/aggressive.config

aggressive.config is as follows: { "redex" : { "passes" : [ "RemoveUnreachablePass", "StripDebugInfoPass", "AccessMarkingPass", "MethodDevirtualizationPass", "ReBindRefsPass", "ResultPropagationPass", "BridgeSynthInlinePass," "FinalInlinePass", "DelSuperPass", "UnreferencedInterfacesPass", "SingleImplPass", "CommonSubexpressionEliminationPass", # Run once just before MethodInlinePass "MethodInlinePass", "PeepholePass", "ConstantPropagationPass", "LocalDcePass", "AnnoKillPass", "DelInitPass", "RemoveUnreachablePass", "ReorderInterfacesDeclPass", "RemoveEmptyClassesPass", "SingleImplPass", "InterDexPass", "CommonSubexpressionEliminationPass", # Run a second time after all method inlining is done "RemoveGotosPass", "DedupBlocksPass", "UpCodeMotionPass", "RegAllocPass", "CopyPropagationPass", "LocalDcePass", "DedupBlocksPass", "ReduceGotosPass" # This pass should come at the very end, after all other code transformations that might add gotos ] }, "RegAllocPass" : { "live_range_splitting": false }, "inliner": { "throws": true, "multiple_callers": true, "no_inline_annos" : [ "Lcom/fasterxml/jackson/databind/annotation/JsonDeserialize;" ], "blocklist": [], "caller_blocklist": [] }, "FinalInlinePass" : { "propagate_static_finals": true, "replace_encodable_clinits": true, "blocklist_types" : [] }, "AnnoKillPass" : { "keep_annos": [ "Landroid/view/ViewDebug$CapturedViewProperty;", "Landroid/view/ViewDebug$ExportedProperty;", "Landroid/webkit/JavascriptInterface;", "Landroid/widget/RemoteViews$RemoteView;", "Lcom/google/android/gms/common/annotation/KeepName;" ], "kill_annos" : [ "Lcom/google/inject/BindingAnnotation;" ], "force_kill_annos" : [ "Ldalvik/annotation/EnclosingClass;", "Ldalvik/annotation/EnclosingMethod;", "Ldalvik/annotation/InnerClass;", "Ldalvik/annotation/MemberClasses;", "Ldalvik/annotation/Throws;" ] }, "CopyPropagationPass" : { "eliminate_const_literals": false, "full_method_analysis": true }, "MethodDevirtualizationPass" : { "staticize_vmethods_not_using_this" : true, "staticize_dmethods_not_using_this" : true }, "StripDebugInfoPass" : { "drop_all_dbg_info" : false, "drop_local_variables" : true, "drop_line_numbers" : false, "drop_src_files" : true, "use_allowlist" : false, "cls_allowlist" : [], "method_allowlist" : [], "drop_prologue_end" : true, "drop_epilogue_begin" : true, "drop_all_dbg_info_if_empty" : true }, "PeepholePass" : { "disabled_peepholes": [ "Replace_PutGet", "Replace_PutGetWide", "Replace_PutGetObject", "Replace_PutGetShort", "Replace_PutGetChar", "Replace_PutGetByte", "Replace_PutGetBoolean" ] }, "keep_packages": [ "Lcom/fasterxml/jackson/", "Lcom/google/dexmaker/mockito/" ], "debug_info_kind": "no_custom_symbolication", "method_move_map" : "redex-moved-methods-map.txt", "string_sort_mode" : "class_order", "bytecode_sort_mode" : ["method_similarity_order", "class_order"], "ir_type_checker": { "run_after_each_pass" : false, "verify_moves" : false } }

123zhangmiao avatar Oct 19 '22 06:10 123zhangmiao

@thezhangwei hi~Can you answer my questions above?

123zhangmiao avatar Oct 24 '22 02:10 123zhangmiao

How do I see what a pass does? What are the criteria for whether a pass is valuable?

We have docs for the passes: https://github.com/facebook/redex/blob/main/docs/passes.md Each pass will collect some metrics and put them into the redex-stats.txt file. You can inspect the file to see how effective they are for your input. Note that it's input dependent.

thezhangwei avatar Oct 24 '22 17:10 thezhangwei

The json error was fixed in https://github.com/facebook/redex/commit/52e44ae995172ccaa2d102cf984cb4248cb3b9d9.

thezhangwei avatar Nov 01 '22 00:11 thezhangwei

What are the criteria for whether a pass is valuable?

In general, most passes work towards reducing the final size. Some passes don't do all of the cleanup work and would require a RemoveUnreachablePass to run after to actually remove newly unreachable classes/methods/fields.

Some passes are geared towards improving performance while regressing size, e.g. PerfMethodInlinePass.

Some passes are necessary to produce valid dexes, e.g. InterDexPass and RegAllocPass.

NTillmann avatar Nov 03 '22 18:11 NTillmann