-
Notifications
You must be signed in to change notification settings - Fork 0
Optimizing Code
By default Emscripten will compile code in a fairly safe way, and without all the possible optimizations. You should generally try this first, to make sure things work properly (if not, see the Debugging page). Afterwards, you may want to compile your code so it runs faster. This page explains how.
Note: You can also optimize the source code you are compiling into JavaScript, see Optimizing the source code.
The recommended way to optimize code is with emcc. emcc works like gcc, and basic usage is presented in the Emscripten Tutorial. As mentioned there, you can use emcc to optimize, for example
emcc -O2 file.cpp
To see what the different optimizations levels do, run
emcc --help
- The meaning of
-O1, -O2
etc. in emcc are not identical to gcc/clang/other compilers, even though they have been chosen to be as familiar. They can't be, because optimizing JavaScript is very different than optimizing native code. See the--help
as mentioned before for details. - If you compile several files into a single JavaScript output, be sure to specify the same optimization flags during all invocations of emcc - both when compiling sources into objects, and objects into JavaScript or HTML. See Building Projects for more details.
- Aside from
-Ox
options, there are--llvm-lto
options that you can read about inemcc --help
.
The following procedure is how you should normally optimize your code:
- First, run emcc on your code without optimization. The default settings are set to be safe. Check that your code works (if not, see the Debugging page) before continuing.
- Build with
-O2
. That uses only safe optimizations, and should give good speed in most cases. If this is fast enough for you, you can stop here. If you must have all possible speed, continue. - Optionally, try
-O3
. If that works, great, but generally it will not, since it does some unsafe optimizations that can break code. If the code breaks, look inemcc --help
under -O3 for the settings it changes, you can try to compile with-O2
plus each of those separately to see which will work. See also the next section on advanced compiler settings.
There are several flags you can pass to the compiler to affect code generation, many of which can affect performance. Look in src/settings.js
for which options are available and what they mean, and in apply_opt_level
in tools/shared.py
for how -O1,2,3 affect them.
Most of the relevant ones for purposes of optimization are already turned on for you in -O2. An additional one you might want to consider is OUTLINING_LIMIT, see this blogpost.
In -O1
and above exception catching is disabled. This prevents the generation of try-catch blocks, which lets the code run much faster. To re-enable them, run emcc with -s DISABLE_EXCEPTION_CATCHING=0
.
If you run emcc with EMCC_DEBUG=1
(so, something like EMCC_DEBUG=1 emcc
), then it will output all the intermediate steps after each optimization pass. The output will be in TEMP_DIR/emscripten_temp
, where TEMP_DIR
is by default /tmp
(and can be modified in ~/.emscripten
). EMCC_DEBUG=2
will output even more information, a separate file will be saved for each JS optimization pass.
Inlining often generates large functions. These allow the compiler's optimizations to be more effective, but have downsides for JS engines: They often do not try to optimize big functions for fear or long JIT times, or they do JIT them and it causes noticeable pauses.
You can try to avoid this issue by disabling inlining in specific files, or by using the outliner feature, see (http://mozakai.blogspot.com/2013/08/outlining-workaround-for-jits-and-big.html)[this blog post].