25 September 2026 · 3 min
We create new strings all the time. How quickly can you produce short strings in your programming languge? To create a meaningful string, we convert an integer to a string. In Python, that is str(i). The loop stores each new string in a small ring buffer of 1024 slots, so that the engine cannot simply discard the work.
def from_int(n):
b = buf
for i in range(n):
b[i & 1023] = str(i)
In JavaScript (Node.js and Bun), I use String(i):
function from_int(n) {
for (let i = 0; i < n; i++) buf[i & 1023] = String(i);
}
In C++, I use std::to_string:
void from_int(uint64_t n) {
for (uint64_t i = 0; i < n; i++) buf[i & 1023] = std::to_string(i);
}
In Rust, I use the standard to_string() and, as an alternative, the popular itoa crate, which is designed for fast integer formatting:
fn std_to_string(buf: &mut [String], n: u64) {
for i in 0..n {
buf[(i & 1023) as usize] = i.to_string();
}
}
fn itoa_to_string(buf: &mut [String], n: u64) {
let mut b = itoa::Buffer::new();
for i in 0..n {
buf[(i & 1023) as usize] = b.format(i).to_owned();
}
}
In Go, I use strconv.Itoa:
func fromInt(n int) {
for i := 0; i < n; i++ {
buf[i&1023] = strconv.Itoa(i)
}
}
In Nim, I use the $ operator:
proc fromInt(n: int) =
for i in 0 ..< n:
buf[i and 1023] = $i
The integers go from 0 to 100 million (10 million in Python), so each string has up to eight digits. I report the best of five runs on an Apple M4 Max. C++ is compiled with -O3, Rust in release mode, Nim with -d:danger.

Millions of strings per second:
Python is the slowest at 44 ns per string, about three times slower than JavaScript and eight times slower than C++.
The compiled languages that allocate each string on the heap (Rust, Go, Nim) end up in the same range as JavaScript: 12 to 16 ns per string. Rust with its standard to_string() is even a bit slower than Node.js and Bun. Garbage-collected runtimes like Go and JavaScript are very good at allocating many small, short-lived objects.
C++ wins by a wide margin at 5.4 ns per string. The trick is the small string optimization: a std::string stores short strings, directly inside the object. Our strings have at most eight digits, so C++ never calls the memory allocator.
Versions used: macOS 15.7.7, CPython 3.14.5, Node.js 25.9.0, Bun 1.4.2, Apple clang 17.0.0 (clang-1700.6.4.2) with libc++, rustc 1.94.1 with itoa 1.0.18, Go 1.24.3, Nim 2.2.12.
Daniel Lemire, "How many strings can you create per second?," in Daniel Lemire's blog, September 25, 2026, https://lemire.me/blog/2026/09/25/how-many-strings-can-you-create-per-second/.
[BibTeX]
i guessed correctly at first glance. i had taken a mandatory c++ programming course during my engineering studies; i learnt about memory usage calculations back then, but the result for python surprised me 😀
@Daniel,
You may want to take a look at this:
https://www.reddit.com/r/rust/comments/1wvv4k5/comment/pdf7ucn/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button
On my Macbook it took around 1.45 seconds to do generate one-hundred million strings in Swift compiling with “swiftc -parse-as-library -O”.
swift-driver version: 1.168.6 Apple Swift version 6.4 (swiftlang-6.4.0.34.1 clang-2100.3.34.1)
Target: arm64-apple-macosx26.0
macOS Tahoe 26.6.2
Apple M4
24 GiB of RAM
Code:
Thanks for the report.