Performance Benchmarks
How Strada compares to Perl and Python across real workloads.
Strada compiles to C, then to native machine code via GCC. This gives it a fundamental advantage over interpreted languages for CPU-bound work. These benchmarks compare Strada against Perl 5 and CPython 3 across five categories covering arithmetic, function calls, object-oriented programming, string processing, and data structures.
Results
All times are CPU time (user) in seconds, measured on the same machine. Lower is better.
| Benchmark | Strada | Python 3 | Perl 5 |
|---|---|---|---|
| Compute | 51.94s | 155.85s | 294.87s |
| Functions | 1.80s | 5.57s | 5.40s |
| OOP | 3.94s | 3.17s | 6.90s |
| Strings | 0.79s | 644.15s | 0.90s |
| Array/Hash | 0.76s | 3.22s | 2.46s |
Strada vs Perl
Strada wins convincingly across the board. The Array/Hash benchmark saw a dramatic improvement thanks to tagged integers — small integers are now encoded directly in pointers with zero heap allocation, eliminating millions of malloc/free calls in tight loops.
Strada vs Python
The string benchmark is the standout: Strada's compiled PCRE2 regex and in-place string operations are over 800x faster than Python's interpreted approach. Tagged integers give Strada a 4.2x advantage on the Array/Hash benchmark, where integer-heavy loops benefit from zero-allocation arithmetic. Python edges ahead on OOP thanks to CPython's heavily optimized __getattr__ fast paths and dict internals that have been tuned for decades.
Why Strada is Fast
Native code, not bytecode
Perl and Python compile to bytecode that runs on a virtual machine. Every operation — every addition, every function call, every attribute access — goes through an interpreter dispatch loop. Strada compiles to C, which GCC then optimizes into native machine code. There is no interpreter overhead at runtime.
Zero-overhead function calls
In Perl, calling a function means looking up the symbol table at runtime. In Python, function objects are fetched from dictionaries. In Strada, function calls compile to direct C function calls — a single call instruction. This makes Strada 3.0x faster than Perl and 3.1x faster than Python at function-heavy workloads.
Inline accessor 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 the entire method dispatch machinery. Combined with arithmetic expression inlining (sub-expressions like x*x + y*y compile to raw C arithmetic without intermediate allocations), OOP-heavy code runs 1.8x faster than Perl.
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, not interpreted at match time. Combined with in-place string mutation (strada_concat_inplace avoids copies), string operations are 814x faster than Python and competitive with Perl.
Tagged integers: zero-allocation arithmetic
Strada encodes small integers directly inside pointers using tagged pointer representation. When the low bit of a pointer is set, the remaining 63 bits hold the integer value — no heap allocation, no reference counting, no free. This makes integer-heavy operations like loop counters, array indexing, and hash lookups dramatically faster. The Array/Hash benchmark runs in just 0.76s, making Strada 3.2x faster than Perl and 4.2x faster than Python on data-structure workloads. Functions like strada_to_int() handle both tagged and heap-allocated integers transparently.
Where Perl and Python win
Python edges ahead on OOP thanks to CPython's heavily optimized __getattr__ fast paths and decades of dict tuning. For pure object creation and method dispatch, CPython's specializing bytecode compiler gives it an advantage. Strada is closing this gap with inline accessor optimization and arithmetic expression inlining.
What Each Benchmark Tests
Compute
Tight arithmetic loops and recursive Fibonacci. Tests raw numeric throughput and function call overhead in recursive contexts. Strada's compiled arithmetic maps directly to CPU instructions, giving it a large advantage.
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.
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();
}
Strings
Concatenation of 2.5 million characters, splitting 100K strings, and regex search-and-replace. 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.
Running the Benchmarks
All benchmark source files are in the benchmarks/ directory with implementations in Strada, Python, and Perl:
# Build and run all Strada benchmarks
for b in benchmarks/bench_*.strada; do
./strada "$b"
time ./$(basename "$b" .strada)
done
# Compare with Python and Perl
time python3 benchmarks/bench_compute.py
time perl benchmarks/bench_compute.pl