# Static vs dynamic dispatch in Rust benchmark — for those who care about runtime performance

**URL:** <https://users.rust-lang.org/t/static-vs-dynamic-dispatch-in-rust-benchmark-for-those-who-care-about-runtime-performance/142814>\
**Category:** uncategorized\
**Created:** [October 4, 2026, 2:47am UTC](https://users.rust-lang.org/t/static-vs-dynamic-dispatch-in-rust-benchmark-for-those-who-care-about-runtime-performance/142814 "2026-10-04T02:47:48Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![amid.ukr](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/amid.ukr/32/52112_2.png) [@amid.ukr](https://users.rust-lang.org/u/amid.ukr)\
**Post date:** [October 4, 2026, 2:47am UTC](https://users.rust-lang.org/t/static-vs-dynamic-dispatch-in-rust-benchmark-for-those-who-care-about-runtime-performance/142814/1 "2026-10-04T02:47:48Z")

</div>

All the details, benchmark code, generated assembly, and explanation are in the README:

[https://github.com/amidukr/rust-devirtualization-test](https://github.com/amidukr/rust-devirtualization-test)

> **[GitHub - amidukr/rust-devirtualization-test: Rust static vs dynamic dispatch benchmark with...](https://github.com/amidukr/rust-devirtualization-test)**
>
> Rust static vs dynamic dispatch benchmark with generated assembly and devirtualization examples.

 ![image](https://us1.discourse-cdn.com/flex019/uploads/rust_lang/original/3X/2/a/2ac681b2522b28dd171b92b56e93ca7b68f97767.jpeg)

## UPD

Made the dynamic-dispatch part more accurate.

The measured difference increased from **~3.5× to ~4.9×**.

Changed:

```rust
// was
x = op.apply(std::hint::black_box(x));

```

to:

```rust
// now
x = std::hint::black_box(op).apply(std::hint::black_box(x));

```

Which changed the generated assembly from:

```asm
; was
call r15

```

to:

```asm
; now
call qword ptr [rax + 24]

```

The previous version allowed LLVM to hoist the vtable method pointer out of the loop. The updated version performs the vtable method lookup on each iteration.

---

<div class="post-metadata">

**Author:** ![Jookia](https://avatars.discourse-cdn.com/v4/letter/j/5daacb/32.png) [@Jookia](https://users.rust-lang.org/u/Jookia)\
**Post date:** [October 4, 2026, 4:36am UTC](https://users.rust-lang.org/t/static-vs-dynamic-dispatch-in-rust-benchmark-for-those-who-care-about-runtime-performance/142814/2 "2026-10-04T04:36:44Z")

</div>

The README goes a lot in to how this benchmark is made but cuts off mid sentence as it explains what the benchmark demonstrates. So what does this demonstrate?

Edit: On my computer the results are much different:

```rust
run 1: static = 592.395 ms | dynamic = 1229.125 ms | dynamic/static = 2.07x
run 2: static = 666.677 ms | dynamic = 1281.886 ms | dynamic/static = 1.92x
run 3: static = 768.886 ms | dynamic = 1193.847 ms | dynamic/static = 1.55x
run 4: static = 502.110 ms | dynamic = 1190.254 ms | dynamic/static = 2.37x
run 5: static = 698.196 ms | dynamic = 1154.300 ms | dynamic/static = 1.65x

```

The benchmark seems to be trying to measure the CPU's branch predictor? Or clock speed?

---

<div class="post-metadata">

**Author:** ![amid.ukr](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/amid.ukr/32/52112_2.png) [@amid.ukr](https://users.rust-lang.org/u/amid.ukr)\
**Post date:** [October 4, 2026, 8:06pm UTC](https://users.rust-lang.org/t/static-vs-dynamic-dispatch-in-rust-benchmark-for-those-who-care-about-runtime-performance/142814/3 "2026-10-04T20:06:47Z")

</div>

Interesting. Perhaps your CPU is doing a better job with indirect branch prediction.

I was running it on:

- CPU: 12th Gen Intel(R) Core(TM) i7-1255U (Low-Power Laptop CPU)
- Power Mode: Balanced
- OS: Linux Kernel 7.0.0

I’ve added that to the `README.md`.

Something I forgot to mention: it is important to run the benchmark in **release mode** :

```bash
cargo run --release -p devirtualization-test-main

```

A debug build may not perform the same inlining and devirtualization optimizations.

The screenshot explains pretty much exactly what is being tested.

 ![image](https://us1.discourse-cdn.com/flex019/uploads/rust_lang/original/3X/2/a/2ac681b2522b28dd171b92b56e93ca7b68f97767.jpeg)

It compares vtable-based `dyn` dispatch with plain inlined static dispatch: essentially

```asm
call qword ptr [rax + 24]

```

versus the operation being inlined directly into the loop.

By the way, I’ve also updated the test to make the vtable call more explicit/accurate. I’m now getting a **~4.9× difference** on my machine.
