Skip to content
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

Binary size larger than advertized #66

Open
frehberg opened this issue Oct 11, 2018 · 4 comments
Open

Binary size larger than advertized #66

frehberg opened this issue Oct 11, 2018 · 4 comments

Comments

@frehberg
Copy link

frehberg commented Oct 11, 2018

Summary

Compiling a test-app with different settings (dlmalloc and wee_alloc) the resulting binary sizes of wee_alloc builds are not as small as expected. Benefit is just 3KB, the relation is 25KB for dlmalloc-builds compared to 22KB for wee_alloc-builds with code using simple String-allocation.
see

With an application without any dynamic memory allocation, wee_alloc is adding 2500 bytes:

   829  wasm-game-of-life-dlmalloc/pkg/wasm_game_of_life_bg.wasm
3666  wasm-game-of-life-wee_alloc/pkg/wasm_game_of_life_bg.wasm

With an application using simple String allocation, wee_alloc is adding ca 21000 bytes, being just 3KB better than dlmalloc.

25179  wasm-game-of-life-dlmalloc-dyn/pkg/wasm_game_of_life_bg.wasm
22141  wasm-game-of-life-wee_alloc-dyn/pkg/wasm_game_of_life_bg.wasm

Steps to Reproduce

git clone https://github.com/frehberg/wasm-dyn-mem.git
cd wasm-dyn-mem/rust-bindgen
make build print-sizes

Expected Results

Linking against wee_alloc instead of dlmalloc I expected binaries being much more smaller and gaining larger benefit compared to dlmallic. Just, in some cases the binary is larger and the relation is just 22KB vs 25KB
Maybe wee_alloc is using some code-patterns that can not be optimized as good as expected

@fitzgen
Copy link
Member

fitzgen commented Oct 11, 2018

The dynamic allocation example is measuring a whole lot more than just dynamic allocation: string formatting is rather heavy, and I suspect it is pulling in the panicking infrastructure as well.

If you are trying to specifically measure the code size of allocators, I suggest something more targeted, like https://github.com/rustwasm/wee_alloc/blob/master/example/src/lib.rs

You can built that with the ./build.sh script in this repo. If size classes are disabled, I get a 1,148 bytes binary, and if I enable size classes, then I get a 1,415 bytes binary (after wasm-gc and wasm-opt):

1148 ../target/wasm32-unknown-unknown/release/wee_alloc_example.gc.opt.wasm
1415 ../target/wasm32-unknown-unknown/release/wee_alloc_example.size_classes.gc.opt.wasm

@sffc
Copy link

sffc commented Nov 10, 2019

I have the following lib.rs file:

use wasm_bindgen::prelude::*;
use wee_alloc::WeeAlloc;

// Use `wee_alloc` as the global allocator.
#[global_allocator]
static ALLOC: WeeAlloc = WeeAlloc::INIT;

#[wasm_bindgen]
extern "C" {
	fn alert(s: &str);
}

#[wasm_bindgen]
pub fn greet(name: &str) {
	alert(name);
}

When I compile that using wasm-pack and then inspect the output using twiggy, I get:

 Shallow Bytes │ Shallow % │ Item
───────────────┼───────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
          1353 ┊    25.55% ┊ "function names" subsection
          1065 ┊    20.11% ┊ data[0]
           580 ┊    10.95% ┊ <wee_alloc::WeeAlloc as core::alloc::GlobalAlloc>::alloc::h56b2fbb231097050
           574 ┊    10.84% ┊ wee_alloc::alloc_first_fit::hc3745372ad8f8d4e
           327 ┊     6.18% ┊ wee_alloc::WeeAlloc::dealloc_impl::{{closure}}::h92c7acfcf75e2e63
           252 ┊     4.76% ┊ <wee_alloc::size_classes::SizeClassAllocPolicy as wee_alloc::AllocPolicy>::new_cell_for_free_list::h6ef3252c1cc78ab3
           176 ┊     3.32% ┊ <wee_alloc::WeeAlloc as core::alloc::GlobalAlloc>::dealloc::haa7b6f21eac5aae6
           121 ┊     2.29% ┊ <wee_alloc::LargeAllocPolicy as wee_alloc::AllocPolicy>::new_cell_for_free_list::h8d68be1a53220a52
           113 ┊     2.13% ┊ custom section 'producers'
            80 ┊     1.51% ┊ data[1]
            57 ┊     1.08% ┊ __rg_realloc
            56 ┊     1.06% ┊ memcpy
            47 ┊     0.89% ┊ __wbindgen_malloc
            35 ┊     0.66% ┊ import wbg::__wbg_alert_e4f89deb17f7e8ca
            35 ┊     0.66% ┊ __wbindgen_realloc
            26 ┊     0.49% ┊ greet
            21 ┊     0.40% ┊ export "__wbindgen_realloc"
            21 ┊     0.40% ┊ __rust_realloc
            20 ┊     0.38% ┊ export "__wbindgen_malloc"
            17 ┊     0.32% ┊ __rust_alloc
           319 ┊     6.02% ┊ ... and 42 more.
          5295 ┊   100.00% ┊ Σ [62 Total Rows]

Rows 3-8 all appear to be wee_alloc, and it adds up to 2030 bytes. That includes size_classes, but still bigger than the 1.2 KB advertised in the README.

It's still much smaller than the default allocator though.

@frehberg
Copy link
Author

Probably this ticket can be closed now. The size was related to a bug in Rust-lang, as rust kept dependencies to both, wee-alloc and dlmalloc. It was caused by some hard coded function name for an intrinsic in rust-lang, keeping a dependency to dlmalloc.
This caused the Wee-alloc based binary to be even larger than the pure dlmalloc binary.

@sffc
Copy link

sffc commented Nov 10, 2019

When building with opt-level = "s" and then running through wasm-opt -Os, the size gets smaller. It's hard to tell which symbols are which in the wasm-opt output, but even just enabling opt-level = "s" brings the payload down to 1534 bytes. So I guess I just wasn't using opt-level = "s" earlier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants