Why compiling Rust to WebAssembly is slow
Compiling Rust code to WebAssembly with debug information is significantly slower than necessary. A 40-line Rust code example demonstrated this, taking 50 seconds to compile with debug info and just 1.5 seconds without it. This issue is not unique to this specific case, but rather applies to all Rust code compiled for WebAssembly to varying extents.
The slowdown stems from a known LLVM bug that has previously been reported and fixed for the clang compiler, but remains incomplete for LLVM. While debug information can be helpful for profiling WebAssembly binaries, it often goes unused in practice. The debugging data is designed to provide symbol names in stack traces, which is useful for debugging, but can be an unnecessary burden for wasm binaries.
When compiling to WebAssembly, LLVM represents source variables' locations with DBG_VALUE records, storing their current state (register, stack slot, or constant) in LLVM's machine-level intermediate representation (MIR). These records are relevant when code is moved, as a debugger must see the right values to produce correct stack traces. However, when debug info is set to full (debug = 2), LLVM generates a large number of DBG_VALUE records, leading to inefficient handling of these records.
Register Stackify, a backend pass in LLVM, moves definitions before their uses to optimize wasm code. It scans for DBG_VALUE records within a basic block – a straight sequence of instructions without branches. However, with heavy inlining and many records, this process becomes inefficient, with quadratic time complexity. Additionally, Register Stackify leaves old debug records in the instruction list instead of deleting them, causing further inefficiency.
Moreover, when computing cheap values like constants, LLVM re-computes them at every use instead of carrying them around, creating even more records. This inefficient handling of DBG_VALUE records leads to disproportionately slow compilation times for Rust code compiled to WebAssembly, with debug info causing the LLVM pass time to increase from 1.42 seconds to 50.85 seconds in the example provided.
Written by urgent.news from Lobsters's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.