-
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 see if things work properly (if not, see the Debugging page). Afterwards, you may want to compile your code so it runs faster. This page gives some tips on how to do that.
You can optimize the .ll file that Emscripten receives by running optimizations in the compiler that generates the .ll file (clang or llvm-gcc). Or you can run llvm-opt on an LLVM bitcode file. Note that -O3 optimization will generate faster code, but significantly bigger - which can be an issue on the web.
Important: Note that emmaken.py will discard optimization parameters. emmaken's job is just to generate .bc. You can then run llvm-opt on the bitcode file yourself, or pass --optimize to emscripten.py which will run LLVM optimizations. (We should rename that flag...)
An additional optimization you can run before Emscripten is the dead function elimination tool, that is in tools/dead_function_eliminator.py in Emscripten. This tool will scrub an .ll file and remove all functions that cannot be run, leaving only those functions that can be reached (through some chain of calls) from main() or from a global constant. This is useful in reducing the size of the .ll file, which both leads to smaller code and faster compilation, but make sure it doesn't remove functions that you want left in (if you are compiling a library, for example).
CORRECT_SIGNS, CORRECT_OVERFLOWS and CORRECT_ROUNDINGS are needed in some code. They add a lot of runtime overhead though. If you can, disable them entirely by editing src/settings.js, and recompiling your code for them to take effect.
If you can't, try to enable them just for the lines they are needed, by setting the CORRECT_* option to 2 (see the linespecific test for more). Use the CHECK_* options with AUTO_OPTIMIZE to find the relevant lines - you should compile with -g to see the original source file and line numbers in the generated JavaScript. As you add more lines to be corrected, the check will no longer warn about them, so you can recompile and run, finding a single line each time.
Note that you don't necessarily need to recompile each time. You can edit the generated source. unSign, for example, takes as a third parameter whether to ignore problems, so changing that to true will ignore signing on that line.
The following settings are very important for fast code:
-
OPTIMIZE: This will use native JavaScript variables and other enhancements. -
RELOOP: This will generate native JavaScript code flow structures (ifs, loops, etc.), instead of emulating code flow using the switch-in-a-loop pattern. Note that currently using this setting will make the compiler very slow.
Other settings:
-
USE_TYPED_ARRAYS: Typed arrays in JavaScript can be much faster than untyped arrays. However this does not always lead to faster code, so you should check if it does or not. -
FAST_MEMORY: This is the amount of memory that is set to 0 at startup. This tells the JS engine that HEAP should be implemented as a flat fast array, otherwise it may implement HEAP as a hashtable which is extremely slow. This appears to be a problem mainly with V8. Try increasing the value ofFAST_MEMORYif you suspect this is the problem. You can also tryUSE_TYPED_ARRAYSsince they are always flat arrays, however you must then also make sure thatTOTAL_MEMORYis correct.
Advanced settings:
-
QUANTUM_SIZEof 1 can speed up your code, but is dangerous. See Memory Compression. The default is 4, which is the 'normal', safe value.
For additional speed, JavaScript optimizers can be run after Emscripten. The best is probably the Closure Compiler, which both minifies and optimizes the code. The YUI Compressor is also useful (tends to optimize less, but runs faster).