experimental WebAssembly support in Bloaty McBloatface

233 views
Skip to first unread message

Josh Haberman

unread,
Jul 21, 2018, 5:42:22 PM7/21/18
to emscripten-discuss
I just added some experimental support for WebAssembly to my size profiling tool Bloaty McBloatface. I'm a big fan of WebAssembly, and I hope this might be useful:


Below is some sample output from Hello, World.

WebAssembly doesn't seem to have any equivalent of VM addresses, so it might be hard to build a VM memory map like I do with ELF/Mach-O. For now I just left that part out. I would love to hear any feedback about whether this would make sense in a WebAssembly context. Maybe we could size-profile the VM size of data, even if this doesn't work for code?

Also, I haven't looked into the contents of the .debug_* sections. I've heard that this is DWARF; maybe I could mine this info for more size-profiling info.

Best,
Josh

$ ./bloaty main.wasm -n 0 -d sections,symbols

     VM SIZE                                     FILE SIZE

 --------------                               --------------

   NAN%       0 .debug_info                    13.6Ki  30.0%

   NAN%       0 .debug_str                     9.38Ki  20.8%

   NAN%       0 .debug_line                    7.60Ki  16.8%

   NAN%       0 .debug_abbrev                  4.14Ki   9.2%

   NAN%       0 Code                           3.86Ki   8.6%

       NAN%       0 puts                           1.62Ki  41.9%

       NAN%       0 writev_c                          365   9.2%

       NAN%       0 fwrite                            359   9.1%

       NAN%       0 __stdio_close                     289   7.3%

       NAN%       0 __syscall_ret                     198   5.0%

       NAN%       0 dummy                             175   4.4%

       NAN%       0 __lockfile                        165   4.2%

       NAN%       0 __syscall3                        121   3.1%

       NAN%       0 __overflow                        107   2.7%

       NAN%       0 fputs                             107   2.7%

       NAN%       0 __wasm_call_ctors                  96   2.4%

       NAN%       0 __syscall4                         93   2.4%

       NAN%       0 main                               92   2.3%

       NAN%       0 __errno_location                   35   0.9%

       NAN%       0 __syscall5                         34   0.9%

       NAN%       0 __towrite                          28   0.7%

       NAN%       0 __syscall0                         18   0.5%

       NAN%       0 __syscall1                          5   0.1%

       NAN%       0 __unlockfile                        5   0.1%

       NAN%       0 [section Code]                      4   0.1%

       NAN%       0 putc_js                             3   0.1%

   NAN%       0 .debug_pubtypes                3.10Ki   6.9%

   NAN%       0 Data                           1.19Ki   2.6%

   NAN%       0 .debug_pubnames                1.05Ki   2.3%

   NAN%       0 .debug_ranges                     353   0.8%

   NAN%       0 name                              310   0.7%

       NAN%       0 __wasm_call_ctors                  19   6.1%

       NAN%       0 __errno_location                   18   5.8%

       NAN%       0 __stdout_write                     16   5.2%

       NAN%       0 __stdio_close                      15   4.8%

       NAN%       0 __stdio_write                      15   4.8%

       NAN%       0 __syscall_ret                      15   4.8%

       NAN%       0 __stdio_seek                       14   4.5%

       NAN%       0 __unlockfile                       14   4.5%

       NAN%       0 [section name]                     12   3.9%

       NAN%       0 __lockfile                         12   3.9%

       NAN%       0 __overflow                         12   3.9%

       NAN%       0 __syscall0                         12   3.9%

       NAN%       0 __syscall1                         12   3.9%

       NAN%       0 __syscall3                         12   3.9%

       NAN%       0 __syscall4                         12   3.9%

       NAN%       0 __syscall5                         12   3.9%

       NAN%       0 __towrite                          11   3.5%

       NAN%       0 writev_c                           10   3.2%

       NAN%       0 putc_js                             9   2.9%

       NAN%       0 __wait                              8   2.6%

       NAN%       0 fwrite                              8   2.6%

       NAN%       0 memcpy                              8   2.6%

       NAN%       0 strlen                              8   2.6%

       NAN%       0 dummy                               7   2.3%

       NAN%       0 fputs                               7   2.3%

       NAN%       0 main                                6   1.9%

       NAN%       0 puts                                6   1.9%

   NAN%       0 .debug_loc                        276   0.6%

   NAN%       0 Import                            102   0.2%

   NAN%       0 Type                               73   0.2%

   NAN%       0 Export                             57   0.1%

   NAN%       0 .debug_macinfo                     38   0.1%

   NAN%       0 Function                           23   0.0%

   NAN%       0 Global                             23   0.0%

   NAN%       0 Element                            12   0.0%

   NAN%       0 [WASM Header]                       8   0.0%

   NAN%       0 Table                               7   0.0%

   NAN%       0 Memory                              5   0.0%

 100.0%       0 TOTAL                          45.1Ki 100.0%

Alon Zakai

unread,
Jul 22, 2018, 1:48:31 PM7/22/18
to emscripten-discuss
Oh wow, nice :) This could be very useful, especially the diffing and other features bloaty has.

As you said, VM size might not make sense for wasm, yeah. How much memory is used when loaded depends on the VM, which might interpret it, or JIT it, in various ways. There is no expected correspondence between a wasm file and how much memory the wasm VM uses at runtime for it.

Testing this out, I see some odd things, maybe a bug? For example, compiling hello world with debug info,

emcc tests/hello_world.c -g -O2

If I do

bloaty -d symbols a.out.wasm

then I see

     VM SIZE                              FILE SIZE
 --------------                        --------------
   NAN%       0 ___syscall6             7.58Ki  55.4%
   NAN%       0 _abort                  2.34Ki  17.1%
   NAN%       0 [35 Others]                646   4.6%
   NAN%       0 ___stdio_write             469   3.3%
   NAN%       0 setTempRet0                397   2.8%
   NAN%       0 [section Import]           328   2.3%
   NAN%       0 ___lockfile                295   2.1%
   NAN%       0 _malloc                    250   1.8%
[..]

But malloc should be the largest by far, and that syscall is just an import (which should be just a few bytes). Running binaryen's --func-metrics size profiling,

wasm-opt a.out.wasm --func-metrics

I see

func: _malloc
 [binary-bytes] : 7750   

7750 out of the total 14017 bytes is 55% - which is what bloaty reported for __syscall6. Perhaps an indexing mixup?

- Alon


--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsub...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Floh

unread,
Jul 22, 2018, 2:21:29 PM7/22/18
to emscripten-discuss
Very cool! I've been using bloaty a lot already for WebAssembly size optimizations (by just using bloaty on a native Mach-O or ELF executable built from the same code), so even without direct WebAssembly support it was already extremely useful!

The most useful feature for me was the size of code in the file, finding the biggest functions, and to find out with the diff-view how the size changes after doing changes to the code. So even without the VM size stuff it would do everything I need :)

Cheers and thanks for the awesome work!
-Floh.

Josh Haberman

unread,
Jul 22, 2018, 3:52:15 PM7/22/18
to emscripten-discuss
On Sunday, July 22, 2018 at 10:48:31 AM UTC-7, Alon Zakai wrote:
Oh wow, nice :) This could be very useful, especially the diffing and other features bloaty has.

I'm really glad. I'm enjoying the chance to get my hands dirty with WebAssembly and learn how it works at a low level.
 
As you said, VM size might not make sense for wasm, yeah. How much memory is used when loaded depends on the VM, which might interpret it, or JIT it, in various ways. There is no expected correspondence between a wasm file and how much memory the wasm VM uses at runtime for it.

Are there any parts of the WebAssembly file that are "flat", so-to-speak? The linear memory section seems to be kind of like this? I'm new to WebAssembly so I'm wondering if there would be any use in profiling the size of this flat memory space.

Testing this out, I see some odd things, maybe a bug? [...] Perhaps an indexing mixup?

Right you are! I didn't realize that function imports were part of the function index space.

I updated my parser to read the import section (changes are up on GitHub) and I seem to be getting better results now:

$ bloaty -d symbols a.out.wasm
     VM SIZE                        FILE SIZE
 --------------                  --------------
   NAN%       0 _malloc           7.56Ki  55.3%
   NAN%       0 _free             2.33Ki  17.1%
   NAN%       0 [35 Others]          678   4.8%
   NAN%       0 _memcpy              462   3.3%
   NAN%       0 ___stdio_write       408   2.9%
   NAN%       0 [section Import]     328   2.3%
   NAN%       0 _memset              291   2.1%
   NAN%       0 ___fwritex           253   1.8%
   NAN%       0 [section Export]     221   1.6%
   NAN%       0 ___overflow          184   1.3%
   NAN%       0 _strlen              140   1.0%
   NAN%       0 _puts                131   0.9%
   NAN%       0 ___stdout_write      120   0.9%
   NAN%       0 ___towrite           120   0.9%
   NAN%       0 ___stdio_seek        114   0.8%
   NAN%       0 _fwrite               97   0.7%
   NAN%       0 _sbrk                 93   0.7%
   NAN%       0 [section Data]        78   0.6%
   NAN%       0 ___stdio_close        60   0.4%
   NAN%       0 [section Type]        45   0.3%
   NAN%       0 ___syscall_ret        43   0.3%
 100.0%       0 TOTAL             13.7Ki 100.0%

Josh Haberman

unread,
Jul 22, 2018, 3:54:25 PM7/22/18
to emscripten-discuss
I'm so glad Bloaty has been useful for you. :)

ydel...@mozilla.com

unread,
Jul 23, 2018, 10:42:59 AM7/23/18
to emscripten-discuss


On Saturday, July 21, 2018 at 4:42:22 PM UTC-5, Josh Haberman wrote:

Also, I haven't looked into the contents of the .debug_* sections. I've heard that this is DWARF; maybe I could mine this info for more size-profiling info.



The .debug_* sections contain more useful information, e.g. for compilation unit or about inlined function. You can already (LLVM7) check the DWARF sections content using llvm-dwarfdump. Looks like the bloaty already has support for reading of the DWARF data, so getting the related data will not be an issue.

DWARF for WebAssembly target is still a work-in-progress, but it will be useful to hear a feedback. There is one outstanding issue about debug information present for the removes functions, however there is a simple workaround exists to exclude that.

Thanks.
Reply all
Reply to author
Forward
0 new messages