Performance Benchmarks
How Strada compares to Perl, Python, Ruby, Node.js, and PHP.
Strada compiles to C, then to native machine code via GCC with link-time optimization. These benchmarks compare Strada against Perl, Python, Ruby, Node.js, and PHP across five categories: compute, functions, strings, data structures, and object-oriented programming.
Results
All times are wall-clock seconds, best of 3 runs. Lower is better.
| Benchmark | Strada | Perl 5.38 | Python 3.12 | Ruby 3.2 | Node.js 18 | PHP 8.3 |
|---|---|---|---|---|---|---|
| Compute | 2.36s | 90.77s | 27.33s | 19.59s | 2.59s | 11.74s |
| Functions | 0.024s | 1.08s | 0.897s | 0.379s | 0.096s | 0.169s |
| Strings | 0.070s | 0.143s | 136.6s | 59.23s | 0.201s | 0.075s |
| Array/Hash | 0.168s | 0.634s | 0.531s | 0.718s | 0.582s | 0.134s |
| OOP | 0.249s | 1.29s | 0.558s | 0.510s | 0.100s | 0.133s |
Strada vs Perl
Strada is a natural upgrade from Perl — same syntax feel, dramatically better performance. The biggest gains come from compiled function calls and integer arithmetic, where Perl's interpreter dispatch loop creates massive overhead.
Strada vs Python
Python's interpreted bytecode VM adds overhead to every operation. Strada compiles to native code, making it dramatically faster across the board. Python's string concatenation with += is catastrophically slow due to immutable string copies — nearly 2,000x slower than Strada.
Strada vs Ruby
Ruby's YARV interpreter and YJIT have improved performance significantly, but Strada's native compilation still wins across every benchmark. Ruby's string concatenation suffers from similar allocation overhead as Python.
Strada vs Node.js
V8's JIT compiler makes Node.js a strong competitor. Strada still wins on compute, strings, array/hash, and function calls thanks to ahead-of-time compilation and tagged integer optimization. Node's V8 JIT excels at OOP with speculative inline caches that optimize method dispatch.
Strada vs PHP
PHP 8.3's JIT and optimized hash tables make it competitive at data-structure workloads. Strada dominates on compute and function calls where native compilation eliminates interpreter overhead.
Why Strada is Fast
Native code, not bytecode
Perl, Python, Ruby, and PHP compile to bytecode that runs on a virtual machine. Node.js uses V8's JIT compiler, which is fast but still has warmup costs and deoptimization overhead. Strada compiles to C, which GCC then optimizes into native machine code with link-time optimization. There is no interpreter overhead at runtime.
Zero-overhead function calls
Interpreted languages look up function names at runtime. Strada compiles function calls to direct C function calls — a single call instruction. With inline fast-path wrappers for tagged integer operations, function call overhead approaches zero. This makes Strada 45x faster than Perl, 37x faster than Python, 16x faster than Ruby, 7x faster than PHP, and 4x faster than Node.js at function-heavy workloads.
Tagged integers: zero-allocation arithmetic
Strada encodes integers directly inside pointers — no heap allocation, no reference counting, no free. Integer arithmetic like $a + $b compiles to a single CPU add instruction plus a bit shift. Reference counting and type conversion functions are inlined at every call site, short-circuiting to a single pointer-bit check for the common integer case. This makes compute-heavy code 38x faster than Perl, 12x faster than Python, 8x faster than Ruby, and 5x faster than PHP.
Refcounted strings: zero-copy sharing
Strada uses StradaString — a refcounted string with the data stored inline (single allocation). When a string is passed to a function or used as a hash key, Strada increments the reference count instead of copying. String literals appended with .= bypass allocation entirely, appending bytes directly to the existing buffer. Short strings are recycled via a pool. This makes string operations 1,952x faster than Python, 846x faster than Ruby, 2.9x faster than Node.js, and 2x faster than Perl.
Inline accessor & constructor optimization
When you write $self->x() on a has attribute, Strada detects that the method is a simple accessor and compiles it to a direct hash fetch — skipping method dispatch entirely. For constructors like Point::new("x", 1, "y", 2), the compiler pre-computes attribute key hashes at compile time, emits direct hash construction code, and devirtualizes method calls for known types. This makes Strada OOP 5.2x faster than Perl, 2.2x faster than Python, and 2x faster than Ruby.
Compiled PCRE2 regex
Strada links against PCRE2 (Perl Compatible Regular Expressions), the same engine used by PHP, Nginx, and Haproxy. Regex patterns are compiled to optimized automata at program startup. Single-character delimiters in split() use SIMD-optimized memchr instead of the regex engine.
Automatic stack trace elision
Strada automatically detects whether your program uses exceptions (try/throw) or introspection (core::caller()). If not, it omits stack frame tracking from every function call, eliminating overhead that Perl and Python always pay. For recursive functions like Fibonacci, this alone provides a significant speedup.
What Each Benchmark Tests
Compute
Sum of 50 million integers and recursive Fibonacci(35) run 30 times. Tests raw numeric throughput, function call overhead, and recursive call performance.
func fib(int $n) int {
if ($n < 2) { return $n; }
return fib($n - 1) + fib($n - 2);
}
Functions
Millions of function calls with multiple arguments, plus Ackermann's function for deep recursion. Tests call/return overhead, argument passing, and stack management.
Strings
Concatenation of 500,000 strings, splitting 100K strings, and regex search-and-replace on 200K iterations. Tests string allocation, PCRE2 regex compilation, and in-place mutation.
Array/Hash
Pushes 2 million elements, creates a 500K-entry hash with lookups, and deletes all entries. Tests dynamic array growth, hash table insertion, lookup, and deletion.
OOP
Creates 1.2 million objects with has attributes, calls accessor methods, computes distances, and performs isa() checks. Tests object construction, method dispatch, accessor performance, and inheritance.
package Point;
has rw int $x = 0;
has rw int $y = 0;
func distance_sq(scalar $self) int {
return $self->x() * $self->x() + $self->y() * $self->y();
}
Running the Benchmarks
All benchmark source files are in the benchmarks/ directory with implementations in Strada, Perl, Python, Ruby, Node.js, and PHP:
# Run all benchmarks with the automated script
cd benchmarks
bash run_benchmarks.sh
# Or run individual benchmarks
./strada benchmarks/bench_compute.strada
time ./bench_compute
time perl benchmarks/bench_compute.pl
time python3 benchmarks/bench_compute.py
time ruby benchmarks/bench_compute.rb
time node benchmarks/bench_compute.js
time php benchmarks/bench_compute.php