DioxusLabs / DioxusLabs/dioxus

managed pre-compiled wasm-bindgen is slower than locally-compiled

Open
#4,017 4 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
Rust
Stars
39.1k
Forks
1.9k
Avg merge
4d 10h
Merged PRs (30d)
4

Description

**Problem**

This is a spin-off from #4011 ("dx serve stalls").

I've researched this some more, and have some surprising findings.

First, I've let `dx serve` run to completion, to make sure the project is fully built, and the cache is warmed up.

Then, I've pressed `r` to rebuild the project. This is that result:

```
14:37:20 [dev] Full rebuild: triggered manually
14:37:34 [dev] Build completed in 2289ms
╭────────────────────────────────────────────────────────────────────────────────────────── /:more ╮
│ App: ━━━━━━━━━━━━━━━━━━━━━━━━━━ 🎉 1.3s Platform: Web │
│ Bundle: ━━━━━━━━━━━━━━━━━━━━━━━━━━ 🎉 12.3s App features: ["web"] │
│ Status: Serving bifrost-frontend 🚀 13.6s Serving at: http://127.0.0.1:8123 │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
```

So it takes `12.3s` to bundle, but only `1.3s` to recompile! This seems excessive.

After some work with `strace`, I found the culprit - it's wasm-bindgen:

```
/home/chrivers/.local/share/dioxus/wasm-bindgen/wasm-bindgen-0.2.100
```

To compare, I cloned `wasm-bindgen`, and did a local compile in release mode.

After placing the resulting binary on top of the one `dx` calls, this is the result:

```
14:38:33 [dev] Full rebuild: triggered manually
14:38:38 [dev] Build completed in 1934ms
╭────────────────────────────────────────────────────────────────────────────────────────── /:more ╮
│ App: ━━━━━━━━━━━━━━━━━━━━━━━━━━ 🎉 1.0s Platform: Web │
│ Bundle: ━━━━━━━━━━━━━━━━━━━━━━━━━━ 🎉 2.4s App features: ["web"] │
│ Status: Serving bifrost-frontend 🚀 3.3s Serving at: http://127.0.0.1:8123 │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
```

Obviously, this is much, much better.

Let's take a look at individual timing.

### Stock:
```
⎋ Timing: 557% cpu --[ 3,185s total: 3,516s user + 14,248s krnl ]--
⩧ Memory: 935 MB max --[ 0 majpf + 414113 minpf ]--
⦺ Events: yield 91441 + forced 1712 // input 0 + output 80224
```

### Locally compiled:
```
⎋ Timing: 280% cpu --[ 1,716s total: 1,840s user + 2,975s krnl ]--
⩧ Memory: 934 MB max --[ 0 majpf + 197682 minpf ]--
⦺ Events: yield 98929 + forced 374 // input 0 + output 80224
```

The stock version is spending most of the time in kernel code. That seems weird.

Related to the `strace` work, I stumbled on something strange. The version of `wasm-bindgen` that comes with Dioxus performs an insane number of allocations with `mmap()`:

```sh
strace -f -tt -e trace=file,execve,desc -s 1024 \
/home/chrivers/.local/share/dioxus/wasm-bindgen/wasm-bindgen-0.2.100 \
--target web --keep-debug \
--out-name bifrost-frontend \
--no-typescript \
--out-dir ${PROJECT_TARGET}/dx/bifrost-frontend/debug/web/public/wasm-bindgen \
${PROJECT_TARGET}/wasm32-unknown-unknown/wasm-dev/bifrost-frontend.wasm \
|& grep mmap | wc -l
91054
```

That's 91054 system calls to `mmap()`! When looking through the output from `strace`, almost all of these are 4K or 8K allocations. It seems something is wrong with the memory allocator.

Here's the locally compiled version:

```sh
strace -f -tt -e trace=file,execve,desc -s 1024 \
wasm-bindgen/target/release/wasm-bindgen \
--target web --keep-debug \
--out-name bifrost-frontend \
--no-typescript \
--out-dir ${PROJECT_TARGET}/dx/bifrost-frontend/debug/web/public/wasm-bindgen \
${PROJECT_TARGET}/wasm32-unknown-unknown/wasm-dev/bifrost-frontend.wasm \
|& grep mmap | wc -l
183
```

Just 183 calls to `mmap()`, which is fine.

**Expected behavior**

I expect the `wasm-bindgen` version that comes with dioxus to be approximately as fast as the one that I can compile myself 😄

**Environment:**

- Dioxus version: `dioxus = { version = "0.6.0", features = [] }`
- Rust version: `rustc 1.85.0 (4d91de4e4 2025-02-17)`
- OS info: `Debian Stable (12.10)`
- App platform: `web`

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.