binaryen icon indicating copy to clipboard operation
binaryen copied to clipboard

Dart deferred loading meta issue

Open biggs0125 opened this issue 5 months ago • 5 comments

The Dart team is experimenting with using binaryen tools to support our deferred loading feature for users targeting wasm. We currently have experimental support for the feature by having the compiler emit multiple modules.

Typically, when emitting a single module, we use wasm-opt with the --closed-world flag to optimize the wasm module that dart2wasm is emitting. This works well for us and sometimes produces 3x code size improvements as well as other structural improvements like inlining, devirtualization, DCE, etc.

Now with deferred loading we are now splitting that single module into many modules that collectively represent the same program. So we technically still have a closed world... but split across multiple modules. Ideally we could specify all these modules to wasm-opt and it would perform the same (or close to the same) optimizations collectively across all these modules. Today wasm-opt doesn't support anything like this.

I've tried implementing this using a combination of wasm-merge -> wasm-opt -> wasm-split but ran into several issues where the code didn't load and the code size didn't improve much.

Associated issues: https://github.com/WebAssembly/binaryen/issues/7725 https://github.com/WebAssembly/binaryen/issues/7724 https://github.com/WebAssembly/binaryen/issues/7723 https://github.com/WebAssembly/binaryen/issues/7722 https://github.com/WebAssembly/binaryen/issues/7721

biggs0125 avatar Jul 15 '25 19:07 biggs0125

Are you seeing that the full type section is duplicated across all of your split modules after wasm-split? If so, you can try running --minimize-recursion-groups as the last optimization in the wasm-opt stage. That could significantly improve the final cumulative code size.

cc @aheejin

tlively avatar Jul 15 '25 20:07 tlively

Our invocation of wasm-opt was already passing --minimize-recursion-groups so I think the type section should be okay. I think most of the bloat comes from the export section.

I've wanted to analyze the size of the different sections in the split file. Normally I would do that using wami --section-stats <my_file.wasm>. But that tool complains there are too many exports in the main module and it gives up. Do you know of any other tools that can help me analyze the wasm file (or workarounds to that limit)?

biggs0125 avatar Jul 16 '25 16:07 biggs0125

https://github.com/google/bloaty has support for wasm files, and shows section sizes.

How many exports are there, btw? (can list them with wasm-opt --metrics -all)

kripken avatar Jul 16 '25 17:07 kripken

wasm-opt --metrics -all works: The original main module file, before the merge->opt->split pass, has 18041 exports.
After the passes are done, the main module has 165168 exports.

biggs0125 avatar Jul 16 '25 18:07 biggs0125

I got bloaty running too and see the following.

Before:

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  52.0%  6.48Mi   NAN%       0    name
  19.4%  2.41Mi   NAN%       0    Code
  12.9%  1.60Mi   NAN%       0    Global
   8.0%  1014Ki   NAN%       0    Import
   2.7%   338Ki   NAN%       0    Type
   2.0%   251Ki   NAN%       0    Export
   1.3%   169Ki   NAN%       0    Element
   1.0%   126Ki   NAN%       0    Data
   0.6%  82.2Ki   NAN%       0    Function
   0.1%  17.1Ki   NAN%       0    Table
   0.0%      50   NAN%       0    sourceMappingURL
   0.0%       8   NAN%       0    [WASM Header]
   0.0%       6   NAN%       0    Event
   0.0%       4   NAN%       0    Start
   0.0%       3   NAN%       0    DataCount
 100.0%  12.5Mi 100.0%       0    TOTAL

After:

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  40.6%  7.60Mi   NAN%       0    name
  24.2%  4.53Mi   NAN%       0    Import
  13.6%  2.54Mi   NAN%       0    Code
   9.8%  1.84Mi   NAN%       0    Global
   7.2%  1.35Mi   NAN%       0    Export
   2.0%   386Ki   NAN%       0    Element
   1.5%   295Ki   NAN%       0    Type
   0.7%   126Ki   NAN%       0    Data
   0.4%  76.6Ki   NAN%       0    Function
   0.1%  16.2Ki   NAN%       0    Table
   0.0%      50   NAN%       0    sourceMappingURL
   0.0%       8   NAN%       0    [WASM Header]
   0.0%       6   NAN%       0    Event
   0.0%       4   NAN%       0    Start
   0.0%       3   NAN%       0    DataCount
 100.0%  18.7Mi 100.0%       0    TOTAL

FWIW here are the sizes of the intermediate files.

After merging 350 modules:

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  51.5%  20.7Mi   NAN%       0    name
  26.6%  10.7Mi   NAN%       0    Code
  11.3%  4.54Mi   NAN%       0    Import
   5.5%  2.21Mi   NAN%       0    Global
   2.5%  1.00Mi   NAN%       0    Type
   0.9%   365Ki   NAN%       0    Function
   0.8%   335Ki   NAN%       0    Element
   0.6%   252Ki   NAN%       0    Export
   0.3%   126Ki   NAN%       0    Data
   0.0%  16.6Ki   NAN%       0    Table
   0.0%      50   NAN%       0    sourceMappingURL
   0.0%       8   NAN%       0    [WASM Header]
   0.0%       7   NAN%       0    Event
   0.0%       4   NAN%       0    Start
   0.0%       3   NAN%       0    DataCount
 100.0%  40.2Mi 100.0%       0    TOTAL

After optimizing merged module:

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  39.3%  8.97Mi   NAN%       0    name
  27.6%  6.30Mi   NAN%       0    Code
  19.8%  4.53Mi   NAN%       0    Import
   8.1%  1.86Mi   NAN%       0    Global
   1.6%   369Ki   NAN%       0    Type
   1.4%   329Ki   NAN%       0    Element
   1.1%   250Ki   NAN%       0    Export
   0.5%   126Ki   NAN%       0    Data
   0.5%   119Ki   NAN%       0    Function
   0.1%  15.3Ki   NAN%       0    Table
   0.0%      50   NAN%       0    sourceMappingURL
   0.0%       8   NAN%       0    [WASM Header]
   0.0%       6   NAN%       0    Event
   0.0%       4   NAN%       0    Start
   0.0%       3   NAN%       0    DataCount
 100.0%  22.8Mi 100.0%       0    TOTAL

The last file is the one that gets split and produces the main module with 165k export.

biggs0125 avatar Jul 16 '25 19:07 biggs0125