cib icon indicating copy to clipboard operation
cib copied to clipboard

Build not fully optimized?

Open kripken opened this issue 7 years ago • 17 comments

clang.wasm is 54315717 bytes. Running binaryen's wasm-opt -O2 shrinks it by around 15%, and -Os by 20%, which suggests maybe it wasn't fully optimized?

I see the build script uses cmake and sets it to release, which should optimize the object files, but I'm not sure how it handles the final link to wasm (in emcc, we need -Os or such during both compile and link). @juj, I think you wrote the emcmake code, what does it do for the final link?

cc @mbebenita

kripken avatar Jan 04 '18 18:01 kripken

Oh wait, is this using emscripten with the LLVM wasm backend, and not fastcomp/asm2wasm? Seems so from the list of repos in build.py. If so, then the 15-20% size difference is not that surprising, as the wasm backend tends to emit larger code. Might be worth adding a build step to run binaryen's optimizer, then.

kripken avatar Jan 04 '18 18:01 kripken

is this using emscripten with the LLVM wasm backend

Yes.

Might be worth adding a build step to run binaryen's optimizer, then.

Sounds good.

tbfleming avatar Jan 04 '18 18:01 tbfleming

If using CMake and e.g. Unix Makefiles generator, then one should pass -DCMAKE_BUILD_TYPE=Release to the build if not otherwise specified, as CMake defaults to building Debug build type, which is unoptimized. emcmake does not reach the linking phase to do any adjustments.

juj avatar Jan 04 '18 18:01 juj

Here's what it currently uses:

  • -DCMAKE_BUILD_TYPE=Release to build llvm's *.a
  • -DCMAKE_BUILD_TYPE=Debug to build the final executable. Release crashes during build.

tbfleming avatar Jan 04 '18 18:01 tbfleming

It's now down to 43M.

tbfleming avatar Jan 04 '18 18:01 tbfleming

I'm a little confused by

@juj: emcmake does not reach the linking phase to do any adjustments.

@tbfleming -DCMAKE_BUILD_TYPE=Debug to build the final executable.

Is cmake issuing the final emcc command to link and generate the executable? I don't see an emcc command in the build script, so it seems like that's the case, but if I understand you @juj that shouldn't be possible?

Release crashes during build.

Oh, do you have an error message or stack trace from that? EMCC_DEBUG=1 in the env could give more info.

kripken avatar Jan 04 '18 19:01 kripken

Is cmake issuing the final emcc command to link and generate the executable?

Yes. Here's the commands which create the app. I'm running it through release to give you a log.

cd /mnt/cib/build/clang-browser-Release/ && emcmake cmake -G "Ninja" -DCMAKE_BUILD_TYPE=Release -DLLVM_BUILD=/mnt/cib/build/llvm-browser-Release/ -DEMSCRIPTEN=on ../../src

cd /mnt/cib/build/clang-browser-Release/ && ninja clang

-DLLVM_BUILD=... and -DEMSCRIPTEN=on are variables in my CMakeLists.txt.

tbfleming avatar Jan 04 '18 19:01 tbfleming

Oops. Sorry; I remembered wrong. It builds but hits this at runtime:

stackAlloc is not defined

tbfleming avatar Jan 04 '18 19:01 tbfleming

1: That stackAlloc issue might be fixed by https://github.com/kripken/emscripten/pull/5986 (Please let me know either way if you check.)

2: Is the relevant CMakeLists.txt this one? https://github.com/tbfleming/cib/blob/master/src/CMakeLists.txt#L105

If so then it looks like cmake is picking the -Ox optimization level for the final link stage. (@juj, is that odd?) Some notes on the flags:

  • Looks like it's using SAFE_HEAP? That can increase size a lot. https://github.com/tbfleming/cib/blob/master/src/CMakeLists.txt#L73
  • I think cmake will emit -O2 for a release build. -O3 could be faster, and -Os could be smaller.
  • NO_EXIT_RUNTIME is now the default, can remove that (unless using an older version).

kripken avatar Jan 04 '18 21:01 kripken

1: I'll try it 2: Yes

I forgot to remove the SAFE_HEAP after debugging.

This reminds me of an issue: NO_EXIT_RUNTIME doesn't stop it from closing stdio. I had to do this instead: https://github.com/tbfleming/cib/blob/master/src/process.js#L137

tbfleming avatar Jan 04 '18 21:01 tbfleming

https://github.com/kripken/emscripten/pull/5986 fixed the stackAlloc issue. I also removed SAFE_HEAP, ASSERTIONS, DEMANGLE_SUPPORT, and NO_EXIT_RUNTIME.

Step 1 Release build 41M
Step 2 wasm-opt -Os 36M
Step 3 combine data segments 37M

Step 3 is because the builds sometimes produce around 130,000 data segments, which exceed Firefox's and Chrome's 100,000 limit. I combine them into a single segment.

tbfleming avatar Jan 04 '18 22:01 tbfleming

Is that stdio issue fixed by https://github.com/kripken/emscripten/pull/6038 ?

About wasm having a 100,000 segment limitation, I wasn't aware of that limit. @lukewagner , is that a temporary thing, or should binaryen work around it?

kripken avatar Jan 07 '18 18:01 kripken

https://github.com/kripken/emscripten/pull/6038 fixed it.

tbfleming avatar Jan 07 '18 20:01 tbfleming

It's a permanent limit and should be the same across browsers since it is in the list of constant limits. If there was a hard reason to relax it, it could be relaxed.

lukewagner avatar Jan 08 '18 18:01 lukewagner

Ok, thanks for the info, I'll handle it in binaryen.

kripken avatar Jan 08 '18 18:01 kripken

@tbfleming https://github.com/WebAssembly/binaryen/pull/1350 should work around the 100K segment limit, please verify it works if you can.

kripken avatar Jan 08 '18 23:01 kripken

@kripken that fixed it. Nice branch name :)

tbfleming avatar Jan 09 '18 17:01 tbfleming