Search code examples
pythonrusthashmap

Why Rust HashMap is slower than Python dict?


I wrote scripts performing the same computations with dict and hashmap in Rust and in Python. Somehow the Python version is more than 10x faster. How is that happens?

Rust script: `

use std::collections::HashMap;
use std::time::Instant;

fn main() {
    let now = Instant::now();

    let mut h = HashMap::new();
    for i in 0..1000000 {
        h.insert(i, i);
    }

    let elapsed = now.elapsed();
    println!("Elapsed: {:.2?}", elapsed);
}

Output: Elapsed: 828.73ms

Python script:

import time

start = time.time()
d = dict()

for i in range(1000000):
    d[i] = i

print(f"Elapsed: {(time.time() - start) * 1000:.2f}ms")

Output: Elapsed: 64.93ms

The same is for string keys. I searched for different workarounds about different hashers for HashMap but none of them is giving more than 10x speed up


Solution

  • Rust by default doesn't have optimizations enabled, because it's annoying for debugging. That makes it, in debug mode, slower than Python. Enabling optimizations should fix that problem.

    This behaviour is not specific to Rust, it's the default for most compilers (like gcc/g++ or clang for C/C++, both require the -O3 flag for maximum performance).

    You can enable optimizations in Rust by adding the --release flag to the respective cargo commands, like:

    cargo run --release
    

    Python doesn't distinguish between with or without optimizations, because Python is an interpreted language and doesn't have an (explicit) compilation step.

    This is the behavior of your code on my machine:

    • Python: ~180ms
    • Rust: ~1750 ms
    • Rust (with --release): ~160ms

    Python's dict implementation is most likely written in C and heavily optimized, so it should be similar in performance to Rust's HashMap, which is exactly what I see on my machine.