Author: Idle Fish technology – Three openings

background

The Wisefish technology team first introduced Flutter technology to realize client development in the first half of 2018. So far, it has successfully adapted and launched complex product details and publishing business. With the increase of transformation business, the volume of installation package increases sharply. The volume of the installation package determines the user’s waiting time for download and the flow that may be consumed. How to control the volume of the installation package and reduce the size of the FLUTTER products has become a top priority. This paper presents some general package size detection and optimization solutions from the perspective of The Xianyu client project practice, hoping to provide a reference for teams interested in Flutter.

Xianyu client adopts the mixed development mode of Flutter and Native. Here, we take ios terminal as an example to analyze the size of Flutter products in the project (ipA package has more urgent requirements for slimness).

The ios project has the following dependencies on Flutter:

  • Flutter. Framework: The Flutter library and engine
  • App. Framework: Dart service source code file
  • A framework of plugins that are compiled into Flutter Plugin
  • Flutter_assets: Static resources that Flutter depends on, such as fonts, images, etc

After the first introduction of the detailed page of the flutter version modification, the IPA package size increased by nearly 20M, including the flutter engine code + the modified service code. After the further release of the page, the IPA increased by 4M+. Further analysis found that the size of Flutter. Framework remained stable at 20M+ after decompressing the IPA file. After adding a new Flutter business — the release page, app. framework increased by nearly 10M!

Flutter. Framework is the code of the Flutter library and engine. There is limited room for optimization.

Product size analysis of Flutter

Run the following command to compile app. framework in release mode and print sizes using print-snapshot-sizes

flutter build aot --release --extra-gen-snapshot-options=--print-snapshot-sizes
Copy the code

The results are as follows:

Building AOT snapshot in release mode (android-arm-release)...      
VMIsolate(CodeSize): 4660
Isolate(CodeSize): 2585632
ReadOnlyData(CodeSize): 2693576
Instructions(CodeSize): 8064816
Total(CodeSize): 13348684
Built to build/aot/.
Copy the code

Instructions: Represents the size of binary code generated after AOT compilation

ReadOnlyData: metadata (such as PcDescriptor, StackMap, CodeSourceMap, etc.) and string size to generate binary code

VMIsolate/Isolate: Represents the sum of the size of the remaining objects (such as constants and virtual machine-specific metadata defined in the code)

At the business level, what if you want to analyze the size of each business module?

  1. Run the following command to compile an arm64 app. framework and put its package structure in the build/aot.json file in the specified directory

    flutter --suppress-analytics build aot --output-dir=build/aot --target-platform=ios --target=lib/main.dart --release --ios-arch=arm64 --extra-gen-snapshot-options="--dwarf_stack_traces,--print-snapshot-sizes,--print_instructions_sizes_to=build/aot.json"
    Copy the code
  2. Use the DART command to convert the aot.json file generated in the previous step into a visually structured web page

    dart ./bin/run_binary_size_analysis.dart  build/aot.json path_to_webpage_dir
    Copy the code

    Dart run_binary_size_analysis.dart is an analysis tool provided by dart. The path to the FLUTTER engine source is as follows:

  3. The index. HTML in the generated folder can be opened to analyze the size occupied by specific businesses. The Large Symbols and Large Files buttons in the upper right corner can directly locate methods/Files with a volume ratio from Large to small.

For example, the above analysis shows PItemInfoInternal. FromJson method takes up a lot of volume, track found the method of main operation is to Map data into objects

PItemInfoInternal.fromJson(Map<dynamic, dynamic> map) {
        id = map['id'] as String;
        attributes = map['attributes'] as String;
        title = map['title'] as String; . }Copy the code

We can infer from this that this type conversion operation results in some very large code being compiled.

Optimization measures

  1. Reduce the display of type conversion operations

    As String/Bool/Int, app. framework will increase the size of the App framework significantly. It will increase the size of the App framework by adding type checking and exception handling logic:

    if (x.classId < A && x.classId > B) throw "x is not subtype of String";
    Copy the code

    400K + volume can be successfully reduced by extracting static common methods.

  2. Reduce the size of the generated code by compiling the parameters — dwarF_STACK_TRACE and –obfuscate

Dwarf_stack_trace indicates that the stack trace symbol is not used in the generated dynamic library file

Obfuscate indicates obfuscate and reduces code size by reducing variable/method names

// Compile the release package and print size flutter build aot --release --extra-gen-snapshot-options=--print-snapshot-sizes //--dwarf_stack_traces, --> reduce the size of flutter build aot --release --extra-gen-snapshot-options="--dwarf_stack_traces,--print-snapshot-sizes"//--obsfuscation, --> reduce the size of flutter build aot --release --extra-gen-snapshot-options="--dwarf_stack_traces,--print-snapshot-sizes,--obfuscate"// Total size decreased by 8.7%Copy the code
  1. You can modify the ios packaging script xcode_backend.sh to delete the dSYM symbol table information file and reduce the size of App. DSYM is a transfer file for storing address mapping information of hexadecimal functions, including symbols we debugged, which is used to analyze crash report file and parse out correct error function information.

    Stripping dSYM out of the framework using the xcrun command can greatly reduce the size of the app. framework.

RunCommand xcrun dsymutil -o "${build_dir}/aot/App.dSYM" "${app_framework}/App"
RunCommand xcrun strip -x -S "${derived_dir}/App.framework/App"
Copy the code
  1. Reduces volume increase caused by flutter and native resource duplication

    By bridging, FLUTTER uses platform-side resource files directly to avoid increasing the package size caused by duplicate resource files.

    The main method is to transmit information on the Flutter and Platform side through BasicMessageChannel. The Flutter end passes the resource name AssetName to the Platform end. After receiving the AssetName, the Platform end locates the resource file based on the name and sends the file back to the Flutter end in binary data format through BasicMessageChannel.

conclusion

The size of the installation package caused by the introduction of the Flutter can cause problems for many technical teams. Through the above measures, the size of the Flutter product App. Framework can be reduced by 30%+. The Xianyu technical team will also consider downloading and lazy loading to reduce the volume occupied by resources in the future. We will continue to make comparisons in code generation to avoid writing larger products, and we will also work with Google to find further optimization space.

Idle fish is looking forward to your joining us

Welcome to join idle Fish to explore more possibilities of Flutter. Resume: [email protected]

reference

  • Github.com/flutter/flu…
  • Github.com/flutter/eng…
  • Github.com/flutter/flu…
  • Github.com/flutter/flu…