- Non-syntax: then
- Using goawk
Non-syntax: then
(on _ x do if x then 2 else 3 end end) @ range 3
(3,2,2)
(on _ x do if x 2 else 3 end end) @ range 3
(3,2,2)
The then is a variable whose value is thrown away, as it's followed by 2.
if 1 then else 2 end
0
then:2 if 1 then else 3 end
2
Using goawk
Goawk is an embeddable awk implementation in go, which offers
- extensions to the language that are implemented in go
- binary deployment as a static executable
These are pretty neat features, but the performance and resource characteristics of goawk are absolutely abysmal compared to GNU Awk, which is itself generally bad compared to the C and even the JS implementation.
Here's Node vs. C:
Benchmark 1 (9 runs): node node.js words7.lil measurement mean ± σ min … max outliers delta wall_time 616ms ± 9.35ms 606ms … 633ms 0 ( 0%) 0% peak_rss 81.4MB ± 826KB 80.2MB … 83.0MB 0 ( 0%) 0% cpu_cycles 3.01G ± 29.9M 2.96G … 3.05G 0 ( 0%) 0% instructions 13.0G ± 23.1M 12.9G … 13.0G 0 ( 0%) 0% cache_references 81.2M ± 6.97M 75.6M … 93.9M 0 ( 0%) 0% cache_misses 8.16M ± 168K 7.88M … 8.40M 0 ( 0%) 0% branch_misses 8.17M ± 162K 7.92M … 8.43M 0 ( 0%) 0% Benchmark 2 (449 runs): lilt words7.lil measurement mean ± σ min … max outliers delta wall_time 11.1ms ± 486us 10.2ms … 15.0ms 26 ( 6%) ⚡- 98.2% ± 0.1% peak_rss 17.4MB ± 121KB 17.0MB … 17.6MB 4 ( 1%) ⚡- 78.7% ± 0.1% cpu_cycles 23.0M ± 768K 22.4M … 33.8M 39 ( 9%) ⚡- 99.2% ± 0.1% instructions 83.8M ± 3.87 83.8M … 83.8M 9 ( 2%) ⚡- 99.4% ± 0.0% cache_references 1.15M ± 23.2K 1.09M … 1.35M 34 ( 8%) ⚡- 98.6% ± 0.8% cache_misses 31.0K ± 1.60K 28.7K … 41.5K 25 ( 6%) ⚡- 99.6% ± 0.2% branch_misses 102K ± 1.43K 99.9K … 127K 8 ( 2%) ⚡- 98.8% ± 0.2%
Then Node vs. GNU Awk:
Benchmark 1 (9 runs): node node.js words7.lil measurement mean ± σ min … max outliers delta wall_time 614ms ± 44.4ms 587ms … 731ms 1 (11%) 0% peak_rss 81.0MB ± 648KB 80.0MB … 82.0MB 0 ( 0%) 0% cpu_cycles 3.06G ± 229M 2.94G … 3.66G 1 (11%) 0% instructions 13.0G ± 18.9M 13.0G … 13.0G 0 ( 0%) 0% cache_references 83.9M ± 18.0M 74.4M … 131M 1 (11%) 0% cache_misses 8.25M ± 255K 7.94M … 8.77M 0 ( 0%) 0% branch_misses 8.13M ± 124K 8.05M … 8.37M 0 ( 0%) 0% Benchmark 2 (3 runs): lila words7.lil measurement mean ± σ min … max outliers delta wall_time 16.3s ± 513ms 15.8s … 16.8s 0 ( 0%) 💩+2552.8% ± 56.3% peak_rss 48.2MB ± 133KB 48.1MB … 48.4MB 0 ( 0%) ⚡- 40.5% ± 1.1% cpu_cycles 65.1G ± 2.31G 63.5G … 67.7G 0 ( 0%) 💩+2025.6% ± 51.2% instructions 201G ± 680 201G … 201G 0 ( 0%) 💩+1447.7% ± 0.2% cache_references 2.94G ± 147M 2.83G … 3.11G 0 ( 0%) 💩+3408.1% ± 120.1% cache_misses 164M ± 8.00M 154M … 168M 0 ( 0%) 💩+1882.6% ± 64.6% branch_misses 10.1M ± 208K 9.93M … 10.3M 0 ( 0%) 💩+ 24.3% ± 2.6%
Then Goawk vs. GNU Awk:
Benchmark 1 (3 runs): ../goawk/goawk -f /usr/local/bin/lila words7.lil measurement mean ± σ min … max outliers delta wall_time 21.9s ± 366ms 21.6s … 22.3s 0 ( 0%) 0% peak_rss 233MB ± 6.17MB 229MB … 240MB 0 ( 0%) 0% cpu_cycles 145G ± 1.17G 144G … 146G 0 ( 0%) 0% instructions 351G ± 620M 350G … 351G 0 ( 0%) 0% cache_references 7.14G ± 164M 6.99G … 7.32G 0 ( 0%) 0% cache_misses 991M ± 7.68M 984M … 999M 0 ( 0%) 0% branch_misses 334M ± 5.00M 329M … 339M 0 ( 0%) 0% Benchmark 2 (3 runs): lila words7.lil measurement mean ± σ min … max outliers delta wall_time 16.1s ± 333ms 15.9s … 16.5s 0 ( 0%) ⚡- 26.4% ± 3.6% peak_rss 48.0MB ± 10.8KB 48.0MB … 48.0MB 0 ( 0%) ⚡- 79.4% ± 4.2% cpu_cycles 64.2G ± 425M 63.9G … 64.7G 0 ( 0%) ⚡- 55.8% ± 1.4% instructions 201G ± 9.92K 201G … 201G 0 ( 0%) ⚡- 42.7% ± 0.3% cache_references 2.91G ± 42.1M 2.87G … 2.95G 0 ( 0%) ⚡- 59.3% ± 3.8% cache_misses 170M ± 4.44M 165M … 174M 0 ( 0%) ⚡- 82.8% ± 1.4% branch_misses 10.3M ± 360K 10.1M … 10.7M 0 ( 0%) ⚡- 96.9% ± 2.4%
On a larger version of this problem, C Lil takes 1s and 1.11GB of memory vs. Goawk Lil which pegged 7 CPUs for more than 40 minutes before I interrupted it.