-
Notifications
You must be signed in to change notification settings - Fork 920
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
wasm: strip debug info and compress relocations #1994
Conversation
Ideally tinygo might follow go's lead here, and aim for a good debugging experience for optimized programs ( https://blog.golang.org/debug-opt ). Failing that, make sure it's easy to debug by adding an option. Removing debug info, with no option to bring it back, feels... strange. So, maybe make it its own option that can be turned on and off? And/or potentially make it -opt 3 ? I dunno much about tinygo optimization. Bigger compilers have both lots of little optimizations which can be controlled individually, and are controlled grossly in groups with -O1, -O2, -O3, or -Os; it would be natural for tinygo to move a bit in that direction. |
I agree that debug information should be available for most targets. However, WebAssembly is a bit different. Here are my considerations:
That said, you've got me convinced that it should be an option (that is probably off by default on WebAssembly for the above reasons). This makes small binaries the default while leaving the option to debug those binaries if needed.
This is actually somewhat unrelated. The blog post describes how to improve debug information that's already present. In short, there is no reason why only unoptimized builds can be debugged (even though that's what many people think). While optimizations will make debugging harder, DWARF has been catching up and adding more and more features that allow it to better debug optimized programs - basically to catch up with modern optimizations. Luckily TinyGo doesn't have to deal with this, mostly. LLVM is responsible for most optimizations and thus also responsible for preserving debug information. The choice that TinyGo can make is whether to emit it at all. |
The blog post said Google wanted to make production binaries work well with debuggers. That's on topic. That said, there's lots of history for debugging defaulting to off back in the old days, so you wouldn't be going out on a huge limb. FWIW I suspect server side wasm would be ok with larger files, and might usually prefer to keep the debug info around to get those sweet, sweet backtraces. I found https://thenewstack.io/the-pain-of-debugging-webassembly/ interesting. I do hope the situation gets better. |
Are there any WebAssembly runtimes that support DWARF other than Chrome? I'm not aware of any but I could be wrong. Note that there is also a "names" section that provides some symbol names and can thus give a rough backtrace (but without accounting for inlining unfortunately). If I remember correctly, Chrome has support for this section. From the blog post you mention:
I'm actually considering doing something like this, for improved GC and scheduler support. While they kind of work at the moment, you can see from bugs like #1966 that they're not working very well. The reason is that WebAssembly is very limited compared to other instruction sets: it doesn't allow direct access to the stack (for security). While there are proposals that would allow TinyGo to work well here (with stack switching and using the host GC), both are still proposals that see very little activity. By modifying WebAssembly after linking, both of these might be possible to implement in a more robust way. |
I agree with @dkegel-fastly; if anything this should be optional. To illustrate this, trying the code in #1981, before this change:
After this change:
|
Sweet! Which runtime is this? Is it public? It shows the source locations (and not just names) so it must be reading the DWARF sections.
Out of interest, what's the reason for looking into TinyGo here? Is it the reduced code size, WASI support, or something else? |
@aykevl this is wasmtime with |
Cool! I just found out right before I saw your comment. I had to update wasmtime from v0.20.0 to v0.28.0 for it to work, though. |
Interestingly, the |
I have an improved branch at dev...debug-flag. It strips debug information at link time instead of at compile time and also replaces the |
Special cases may be confusing, seems like users who want the extra smallness will turn it on. Keeping the debug info around by default will be handy once more runtimes support backtraces. So I'm in the "debuggable by default" camp, I guess. |
Also, I'd just leave the -no-debug flag the way it is; it's shorter to type than -debug=false :-) |
Sorry to weigh in here. As a user, I would give +1 to @dkegel-fastly and I would like to keep debug info by default. At least, we in Envoy/Proxy-Wasm project already have used name sections for emitting backtraces, so I definitely would love to keep name section at least. Anyway thanks for your efforts here to reduce the binary size, that would be awesome for everyone. FWIW, we haven't support DWARF in Envoy proxy yet proxy-wasm/proxy-wasm-cpp-host#149 |
Ok, you got me convinced. I'll keep the defaults as-is, with debug information. I've force-pushed an update.
It was necessary when the default depends on the target (for example, you can't re-enable debug information with
I'm always interested in feedback especially from people affected by the change :) |
That's more like it :-) |
@aykevl some merge conflicts are needing to be resolved, please. |
Reminder to @aykevl to please resolve merge conflict here. Thanks! |
Stripping debug information at link time also allows relocation compression (aka linker relaxations). Keeping debug information at compile time and optionally stripping it at link time has some advantages: * Automatic stack sizes on Cortex-M rely on the presence of debug information. * Some parts of the compiler now rely on the presence of debug information for proper diagnostics. * It works better with the cache: there is no distinction between debug and no-debug builds. * It makes it easier (or possible at all) to enable debug information in the wasi-libc library without big downsides.
Rebased. |
Thanks @aykevl for working on this and thanks to everyone who helped provide feedback and guidance. Now merging. |
This patch reduces code size significantly by stripping debug
information at the link stage and additionally compressing relocations
(which is only possible when debug information has been stripped).
For example, when compiling testdata/alias.go with -target=wasi, I get
the following results:
In other words, by stripping debug information and compressing
relocations by default, the resulting binary is smaller than it would
otherwise be even with -no-debug. Adding -no-debug may give a small
extra reduction in code size, but after this patch it's not very
significant.
This patch currently does not provide a way to opt out of this behavior.
If there is a need, an option can be added at a later time to change
this behavior.
@dkegel-fastly @fgsch because you've been rather involved in WebAssembly lately: what do you think of this change? Is it a good change of defaults?