Static or dynamic dispatch?
| Dimension | Static dispatch | Dynamic dispatch |
|---|---|---|
| Who picks the function | The compiler, from the types it sees | The running program, from the object the call is made on |
| What a call costs | A direct call, or none at all once inlined | A load from a table (vtable, itable) and an indirect call |
| Optimization | The optimizer can inline and optimize across the call | Blocks inlining, unless a JIT sees one type in practice and inlines speculatively |
| Compiled code | One copy per type (monomorphization), so bigger binaries and slower builds | One copy serves every type |
| Mixed-type collections | No: a Vec<T> holds one type | Yes: a Vec<Box<dyn Shape>> holds circles and squares together |
| Types added later | Must exist when the program is compiled | Plugins, subclasses and test fakes work without recompiling the caller |
| In code | Overloads, C++ templates, Rust generics (fn f<T: Trait>), Go generics (partly) | C++ virtual, Rust dyn Trait, Go interfaces, Java and C# interfaces and virtual methods, Python and JavaScript method calls |
Rule of thumb
Default to static dispatch for code on the hot path where every type is known, and to dynamic dispatch where flexibility matters more than a few nanoseconds per call: plugin systems, heterogeneous lists, dependency injection, tests. Many designs mix them: a generic inner loop called from a dyn interface at the edge, or a C++ template that shares its non-generic core through a base class. Measure before switching; JITs such as HotSpot often remove the cost of virtual calls that only ever see one type.
Sources
- The Rust Programming Language: Trait objects (static vs dynamic dispatch, inlining, heterogeneous collections)
- The Rust Programming Language: Generic data types (monomorphization)
- The Rust Reference: Trait objects (vtables)
- The Rust Performance Book: Compile times (generic functions instantiated many times)
- Bjarne Stroustrup: A History of C++, 1979–1991 (HOPL-II), on virtual functions and template code sharing
- Go design doc: Go 1.18 implementation of generics via dictionaries and gcshape stenciling
- Russ Cox: Go data structures: interfaces (itables)
- Oracle: The Java HotSpot performance engine architecture (inlining virtual calls)
- Microsoft Learn: virtual (C# reference)
- Python glossary: duck-typing