APL Performance Benchmarks vs Dyalog APL v20.0 & GNU APL v2.0
APL Run wins or ties 34 of 34 compute benchmarks vs Dyalog APL v20.0 (40 iterations, 95% CI, internal ⎕AI compute timing).
Prime Sieve
| Benchmark | APL Expression | APL Run (Native) | WASM | WASM AOT | Dyalog v20 | GNU APL v2 |
| Primes N=2000 |
(2=+⌿0=∘.\|⍨⍳2000)/⍳2000 |
0.0 ± 0.0 |
0.7 ± 1.1 |
— |
5.1 ± 0.5 |
67.8 ± 2.0 |
| Primes N=4000 |
(2=+⌿0=∘.\|⍨⍳4000)/⍳4000 |
0.0 ± 0.0 |
0.7 ± 1.2 |
— |
18.6 ± 1.0 |
— |
Matrix Multiply
| Benchmark | APL Expression | APL Run (Native) | WASM | WASM AOT | Dyalog v20 | GNU APL v2 |
| MatMul 100×100 |
M←100 100⍴⍳10000 ⋄ +/,M+.×M |
0.1 ± 0.0 |
0.8 ± 1.1 |
— |
0.5 ± 0.2 |
5.2 ± 0.1 |
| MatMul 200×200 |
M←200 200⍴⍳40000 ⋄ +/,M+.×M |
0.6 ± 0.0 |
1.6 ± 1.2 |
— |
1.8 ± 0.3 |
41.2 ± 1.6 |
| MatMul 400×400 |
M←400 400⍴⍳160000 ⋄ +/,M+.×M |
5.2 ± 0.0 |
7.2 ± 2.0 |
— |
9.3 ± 0.5 |
— |
Reductions & Arithmetic
| Benchmark | APL Expression | APL Run (Native) | WASM | WASM AOT | Dyalog v20 | GNU APL v2 |
| Sum ⍳2M |
+/⍳2000000` (★ fused to O(1)) |
0.0 ± 0.0 |
0.5 ± 1.0 |
— |
0.5 ± 0.3 |
9.3 ± 0.2 |
| Sum ?2M⍴1000 |
+/?2000000⍴1000` (materialized) |
2.3 ± 0.1 |
5.4 ± 1.1 |
— |
10.7 ± 0.8 |
21.8 ± 0.7 |
| Arith chain 10M |
+/(3×⍳10000000)+(-⍳10000000) |
4.5 ± 0.0 |
11.0 ± 3.1 |
— |
11.6 ± 1.2 |
187.3 ± 5.2 |
Recursive Dfns
| Benchmark | APL Expression | APL Run (Native) | WASM | WASM AOT | Dyalog v20 | GNU APL v2 |
| Collatz ⍳1K |
+/c¨⍳1000` (recursive dfn) |
1.1 ± 0.0 |
2.0 ± 1.0 |
7.1 ± 0.6 |
29.9 ± 1.0 |
— |
| Collatz ⍳5K |
+/c¨⍳5000` (recursive dfn) |
7.0 ± 0.1 |
10.2 ± 1.0 |
40.5 ± 0.5 |
189.1 ± 2.7 |
— |
| Fibonacci ⍳25 |
+/f¨⍳25` (doubly-recursive dfn) |
6.5 ± 0.0 |
10.4 ± 1.1 |
42.0 ± 0.3 |
325.4 ± 2.6 |
— |
Sort & Newton
| Benchmark | APL Expression | APL Run (Native) | WASM | WASM AOT | Dyalog v20 | GNU APL v2 |
| Sort Int 100K |
v[⍋v]` (100K random ints) |
0.4 ± 0.0 |
1.6 ± 1.3 |
— |
1.9 ± 0.4 |
26.1 ± 1.3 |
| Sort Float 1M |
v[⍋v]` (1M random floats) |
11.0 ± 0.1 |
15.7 ± 2.5 |
— |
17.0 ± 1.0 |
— |
| Sort String 100K |
M[⍋M;]` (100K×10 char matrix) |
4.2 ± 0.2 |
10.2 ± 1.5 |
— |
17.5 ± 0.5 |
— |
| Newton √100K |
{⍵-((⍵*2)-N)÷2×⍵}⍣20⊢N |
1.2 ± 0.1 |
2.6 ± 1.5 |
— |
4.7 ± 0.7 |
— |
| Newton √1M |
{⍵-((⍵*2)-N)÷2×⍵}⍣20⊢N |
10.7 ± 0.1 |
18.4 ± 4.6 |
— |
24.4 ± 1.1 |
— |
LCS (Longest Common Substring)
| Benchmark | APL Expression | APL Run (Native) | WASM | WASM AOT | Dyalog v20 | GNU APL v2 |
| LCS N=80 |
nested dfns, trains, ¨ |
2.7 ± 0.2 |
4.2 ± 1.8 |
— |
6.8 ± 0.5 |
— |
FFT (Cooley-Tukey)
| Benchmark | APL Expression | APL Run (Native) | WASM | WASM AOT | Dyalog v20 | GNU APL v2 |
| FFT 1024 |
recursive dfn, complex ×/+ |
1.3 ± 0.0 |
2.6 ± 1.4 |
— |
3.6 ± 0.4 |
— |
| FFT 4096 |
recursive dfn, complex ×/+ |
4.7 ± 0.1 |
7.3 ± 1.6 |
— |
12.1 ± 0.7 |
— |
Standard Primitives
| Benchmark | APL Expression | APL Run (Native) | WASM | WASM AOT | Dyalog v20 | GNU APL v2 |
| Transpose 3K×3K |
⍉M` (3000×3000 matrix) |
1.5 ± 0.4 |
2.1 ± 1.7 |
— |
16.6 ± 2.5 |
78.5 ± 6.6 |
| Reverse 10M |
⌽v` (10M-element vector) |
1.2 ± 0.2 |
2.1 ± 1.4 |
— |
3.5 ± 0.8 |
68.2 ± 1.6 |
| Membership 2M∊1M |
a∊b` (2M in 1M) |
1.3 ± 0.1 |
6.0 ± 1.1 |
— |
3.6 ± 0.3 |
— |
| Rotate 10M |
100⌽v` (10M-element vector) |
1.2 ± 0.3 |
2.4 ± 1.6 |
— |
2.9 ± 0.5 |
68.4 ± 1.6 |
Erdős Primes
| Benchmark | APL Expression | APL Run (Native) | WASM | WASM AOT | Dyalog v20 | GNU APL v2 |
| Erdős ⍳2500 |
nested dfns, prime test, ¨ |
2.3 ± 0.0 |
4.0 ± 1.3 |
— |
7.0 ± 0.7 |
— |
| Erdős ⍳5000 |
nested dfns, prime test, ¨ |
4.8 ± 0.4 |
5.8 ± 1.1 |
— |
13.8 ± 0.9 |
— |
Lucky Numbers
| Benchmark | APL Expression | APL Run (Native) | WASM | WASM AOT | Dyalog v20 | GNU APL v2 |
| Lucky N=1600 |
recursive sieve, replicate, modulus |
0.3 ± 0.0 |
1.2 ± 1.3 |
— |
1.1 ± 0.2 |
— |
| Lucky N=3000 |
recursive sieve, replicate, modulus |
0.5 ± 0.0 |
2.3 ± 1.3 |
— |
2.2 ± 0.5 |
— |
LSWRC (Unique Substrings)
| Benchmark | APL Expression | APL Run (Native) | WASM | WASM AOT | Dyalog v20 | GNU APL v2 |
| LSWRC N=117 |
tacit defs, trains, compose, ¨ |
0.3 ± 0.1 |
1.2 ± 1.4 |
— |
0.6 ± 0.2 |
— |
| LSWRC N=567 |
tacit defs, trains, compose, ¨ |
2.1 ± 0.4 |
3.4 ± 1.4 |
— |
8.6 ± 0.6 |
— |
Shannon Entropy
| Benchmark | APL Expression | APL Run (Native) | WASM | WASM AOT | Dyalog v20 | GNU APL v2 |
| Shannon N=1500 |
Key (⌸), compose bind, tacit trains |
3.6 ± 0.1 |
9.8 ± 1.9 |
— |
10.8 ± 1.9 |
— |
Munchausen Numbers
| Benchmark | APL Expression | APL Run (Native) | WASM | WASM AOT | Dyalog v20 | GNU APL v2 |
| Munchausen ⍳10K |
tacit train, compose, ⍎¨⍕, *⍨ |
0.6 ± 0.0 |
1.6 ± 1.2 |
— |
89.6 ± 10.2 |
— |
Jaccard Similarity
| Benchmark | APL Expression | APL Run (Native) | WASM | WASM AOT | Dyalog v20 | GNU APL v2 |
| Jaccard 300K |
(≢A∩B)÷≢A∪B` (set ops, deal) |
1.1 ± 0.1 |
3.0 ± 0.2 |
— |
9.2 ± 1.6 |
— |
Bell Triangle
| Benchmark | APL Expression | APL Run (Native) | WASM | WASM AOT | Dyalog v20 | GNU APL v2 |
| Bell N=200×10 |
trains, scan, compose, ⍣N |
1.5 ± 0.0 |
3.4 ± 1.5 |
— |
3.3 ± 0.4 |
— |
Multi-LCS
| Benchmark | APL Expression | APL Run (Native) | WASM | WASM AOT | Dyalog v20 | GNU APL v2 |
| Multi-LCS ×2000 |
tacit train, 3 strings, ↑⌽∧\ |
5.1 ± 0.1 |
8.3 ± 1.7 |
— |
10.5 ± 0.5 |
— |