Closed fitzgen closed 6 years ago
The inlined functions feature require some kind of debugging information that does not exist. Source maps don't have that information, however DWARF does (3.3.8.2):
Each inline expansion of a subroutine is represented by a debugging information entry with the tag DW_TAG_inlined_subroutine. Each such entry is a direct child of the entry that represents the scope within which the inlining occurs.
Each inlined subroutine entry may have either a DW_AT_low_pc and DW_AT_high_pc pair of attributes or a DW_AT_ranges attribute whose values encode the contiguous or non-contiguous address ranges, respectively, of the machine instructions generated for the inlined subroutine (see Section 2.17 following). An inlined subroutine entry may also contain a DW_AT_entry_pc attribute, representing the first executable instruction of the inline expansion (see Section 2.18 on page 55).
There is cargo-bloat which has some initial work on this, but it doesn't support wasm (yet). cc @RazrFalcon .
AFAIU, we need to parse WASM binaries(?) and it's out of scope for cargo-bloat
, because it works on top of goblin
/object
. So first we need a crate that can parse WASM binaries.
For more advanced features we need a better name mangling in rustc, because the current one does not preserve all the information. See https://github.com/rust-lang/rust/issues/45691#issuecomment-358309043
I'm not sure if parity-wasm could do what you need @RazrFalcon but maybe @pepyakin could shed some light on that or if they know of some other crate that might if it exists today.
Yeah, parity-wasm is capable of parsing WASM binaries. Although it still lacks support of reading name section which might be useful for the usecase. However, there is ongoing PR.
Btw, @emk already started something called wasm-bloat !
@pepyakin wasm-bloat
is not moving very quickly, because I'm juggling too many projects. But I see that you finished and merged my work on https://github.com/paritytech/parity-wasm/pull/132 (thank you!), which means that parity-wasm
can now parse all the function bodies in a WASM file, and match them to mangled function names in the source code.
This wouldn't allow you to detect inlined functions (that would require source map support, I think), but for function-level stuff, it means that parity-wasm
should give you almost everything you need to write a nice bloat tool. You could de-mangle the Rust names (there's a crate for that), organize them by module, and figure out the size of each in maybe 250 lines of code, I'd bet.
I may continue work on wasm-bloat
at some point if nobody beats me to adding this to cargo bloat
, but I have a couple of other major disruptions coming up this winter that will reduce my open source bandwidth for a while.
Ok, I've got the start of a code profiler that does a lot of what I laid out in the original comment.
I've filed lots of issues, too, for folks who want to help build it! Happy to mentor / help anyone get up to speed with it.
@fitzgen small heads up that svelte is also the name of a JS UI framework: https://github.com/sveltejs/svelte. Name collisions are unavoidable, and it doesn't seem like they're actively exploring wasm right now but I do see the potential for confusing searches in the future.
Given the advent and integration of Twiggy, I'm gonna close this!
I hacked up a little script here: https://github.com/fitzgen/source-map-mappings/blob/master/source-map-mappings-wasm-api/who-calls.py
But that was just a hacky thing out of necessity. What I really want is:
Lists for functions, crates, and data segments, sorted by largest size
who-calls.py
script does this, and shows callers as well, displayed as a treeTree map visualizations grouped by function, crate, and data segment
List the path(s) in the call graph from any given private function back to an exported function
who-calls.py
does a very basic version of thiswasm-gc
can't statically prove that the code is deadDominator trees to tell me which function F transitively keeps the most code size from other child functions "rooted" in the call graph, even if F itself has a small code size (and so you might otherwise ignore it). By "rooted" I mean "reachable from exported functions in the call graph", ie won't get removed by
wasm-gc
.I want to know which logical functions got inlined into any given physical function in the wasm
.wasm
file?Similarly, I want to be able to investigate monomorphizations of generic functions