plokhotnyuk / benchmarks

Some benchmarks of different languages

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Table of Content

Overview

The benchmarks follow the criteria:

  • They are written as the average software developer would write them, i.e.

    • The algorithms are implemented as cited in public sources;
    • The libraries are used as described in the tutorials, documentation and examples;
    • The used data structures are idiomatic.
  • The used algorithms are similar between the languages (as the reference implementations), variants are acceptable if the reference implementation exists.

  • All final binaries are releases (optimized for performance if possible) as debug performance may vary too much depending on the compiler.

My other benchmarks: jit-benchmarks, crystal-benchmarks-game

Measurements

The measured values are:

  • time spent for the benchmark execution (loading required data and code self-testing are not measured);
  • memory consumption of the benchmark process, reported as base + increase, where base is the RSS before the benchmark and increase is the peak increase of the RSS during the benchmark;
  • energy consumption of the CPU package during the benchmark: PP0 (cores) + PP1 (uncores like GPU) + DRAM. Currently, only Intel CPU are supported via the powercap interface.

All values are presented as: median±median absolute deviation.

UPDATE: 2022-09-23

Test Cases

Brainfuck

Testing brainfuck implementations using two code samples (bench.b and mandel.b). Supports two mode:

  • Verbose (default). Prints the output immediately.
  • Quiet (if QUIET environment variable is set). Accumulates the output using Fletcher-16 checksum, and prints it out after the benchmark.

Brainfuck

bench.b

Language Time, s Memory, MiB Energy, J
Racket (Syntax Objects) 1.293±0.001 111.65±00.71 + 0.00±00.00 46.98±00.02
C++/g++ 1.317±0.000 1.82±00.02 + 0.00±00.00 52.72±00.17
Rust 1.543±0.000 0.93±00.01 + 0.00±00.00 61.72±00.13
Java 1.653±0.003 38.82±00.08 + 0.52±00.07 64.26±00.17
D/ldc2 1.659±0.002 3.01±00.02 + 0.00±00.00 66.27±00.17
D/gdc 1.661±0.000 6.55±00.04 + 0.00±00.00 68.36±00.15
C/gcc 1.667±0.000 0.88±00.01 + 0.00±00.00 64.53±00.04
C/clang 1.670±0.001 0.89±00.01 + 0.00±00.00 64.75±00.07
Kotlin/JVM 1.685±0.004 41.48±00.18 + 0.52±00.16 65.51±00.18
C++/clang++ 1.738±0.000 1.65±00.03 + 0.00±00.00 67.30±00.08
Zig 1.747±0.001 0.92±00.02 + 0.00±00.00 68.37±00.55
C#/.NET Core 1.902±0.001 33.90±00.25 + 0.00±00.00 76.15±00.25
Go 1.905±0.000 2.98±00.07 + 0.00±00.00 73.64±00.17
OCaml 1.911±0.000 2.94±00.02 + 1.98±00.00 86.49±01.35
Chez Scheme 1.922±0.001 24.78±00.04 + 4.44±00.04 79.39±00.12
F#/.NET Core 1.947±0.000 37.85±00.03 + 0.56±00.00 77.86±00.20
Nim/gcc 1.962±0.000 2.01±00.04 + 0.00±00.00 76.63±00.69
Racket 1.986±0.019 92.88±00.44 + 0.00±00.00 80.21±01.03
Vala/gcc 2.090±0.000 4.24±00.09 + 0.00±00.00 78.05±00.32
Nim/clang 2.112±0.001 2.31±00.01 + 0.00±00.00 82.20±00.51
Go/gccgo 2.176±0.001 24.42±00.04 + 0.00±00.00 85.13±00.93
Vala/clang 2.266±0.000 4.32±00.08 + 0.00±00.00 84.95±00.07
V/gcc 2.277±0.000 1.84±00.05 + 0.00±00.00 85.30±00.16
Crystal 2.389±0.003 3.00±00.01 + 0.00±00.00 95.36±00.43
Julia 2.594±0.010 224.45±00.16 + 0.82±00.05 101.61±00.91
MLton 2.608±0.000 0.96±00.02 + 0.90±00.11 102.94±00.56
C#/Mono 2.686±0.001 24.89±00.04 + 0.00±00.00 107.21±00.13
V/clang 2.735±0.002 1.84±00.09 + 0.00±00.00 109.52±00.55
Scala 3.230±0.009 67.12±00.09 + 140.81±00.29 133.10±00.69
D/dmd 3.267±0.000 3.55±00.04 + 0.00±00.00 126.05±00.33
Haskell (MArray) 3.847±0.001 5.87±00.03 + 4.72±00.00 154.08±00.43
Node.js 4.154±0.004 40.49±00.05 + 2.16±00.09 165.56±00.43
Swift 5.446±0.001 13.76±00.07 + 0.00±00.00 205.19±00.30
Lua/luajit 6.484±0.015 2.50±00.03 + 0.00±00.00 258.91±00.55
Ruby/truffleruby 7.494±0.115 297.28±00.54 + 325.55±13.94 359.91±05.75
Ruby/truffleruby (--jvm) 8.155±0.067 352.85±06.71 + 467.10±19.50 392.34±02.92
Python/pypy 12.188±0.033 64.54±00.19 + 30.13±00.10 508.85±01.68
Haskell 15.028±0.010 3.85±00.03 + 7.19±00.04 679.80±08.07
Ruby (--jit) 40.868±0.197 270.47±00.06 + 0.29±00.04 1629.77±07.26
Elixir 43.616±0.243 71.01±00.79 + 0.00±00.00 1985.56±21.21
Lua 50.967±0.319 2.30±00.02 + 0.00±00.00 1955.29±18.53
Ruby/jruby 79.375±0.729 184.40±01.19 + 85.06±01.03 3537.33±31.99
Ruby 86.488±0.104 13.93±00.05 + 0.00±00.00 3604.94±19.73
Python 196.223±1.810 10.42±00.06 + 0.00±00.00 7843.33±119.79
Tcl (FP) 270.436±1.400 3.93±00.09 + 0.00±00.00 11307.54±134.33
Perl 327.444±1.656 6.86±00.09 + 0.00±00.00 13065.18±71.67
Tcl (OOP) 523.177±2.973 3.94±00.07 + 0.00±00.00 22061.79±158.35

mandel.b

Mandel in Brainfuck

Language Time, s Memory, MiB Energy, J
C++/g++ 10.468±0.023 1.80±00.02 + 2.24±00.02 420.90±01.56
Racket (Syntax Objects) 13.780±0.048 111.45±00.23 + 67.60±00.23 550.03±02.02
C/gcc 14.200±0.006 0.88±00.03 + 0.87±00.03 560.07±04.35
Kotlin/JVM 14.292±0.005 41.54±00.18 + 1.45±00.21 586.01±00.99
V/gcc 14.450±0.014 2.22±00.05 + 0.77±00.00 577.29±00.51
Rust 14.787±0.016 0.92±00.01 + 1.36±00.06 577.08±03.69
D/ldc2 14.924±0.016 2.94±00.01 + 0.88±00.02 595.92±00.62
C++/clang++ 15.012±0.015 1.65±00.02 + 1.93±00.03 605.63±03.12
C/clang 15.122±0.013 0.90±00.02 + 0.90±00.00 647.01±03.97
D/gdc 15.238±0.081 6.56±00.03 + 1.46±00.03 636.13±04.29
Go 16.157±0.020 3.20±00.28 + 1.27±00.00 630.11±03.88
Zig 16.239±0.020 0.92±00.01 + 1.31±00.00 658.86±05.07
Swift 18.131±0.057 14.67±00.06 + 0.00±00.00 735.20±10.83
Java 18.294±0.023 37.71±00.35 + 1.88±00.36 730.92±00.72
Vala/gcc 18.477±0.005 4.20±00.03 + 1.77±00.04 691.66±00.34
C#/.NET Core 18.540±0.014 34.15±00.06 + 0.83±00.01 740.52±01.15
Go/gccgo 19.905±0.008 24.46±00.03 + 1.27±00.00 832.05±07.20
Vala/clang 20.240±0.005 4.20±00.06 + 1.73±00.08 783.19±00.73
Scala 20.996±0.005 68.20±00.10 + 141.33±00.29 877.97±01.76
V/clang 21.510±0.078 1.85±00.10 + 1.15±00.09 895.32±04.49
Crystal 21.595±0.016 2.98±00.01 + 0.69±00.05 860.94±02.42
Nim/gcc 22.723±0.079 1.98±00.02 + 0.52±00.00 924.02±07.74
Nim/clang 25.539±0.346 2.26±00.01 + 0.57±00.00 1016.20±13.25
OCaml 26.225±0.042 3.45±00.03 + 3.79±00.09 1240.48±07.92
Chez Scheme 26.957±0.030 25.36±00.02 + 3.93±00.02 1185.16±06.29
Julia 29.496±0.070 224.62±00.21 + 0.70±00.02 1123.15±08.96
Node.js 29.634±1.152 40.57±00.07 + 5.37±00.00 1250.41±55.67
C#/Mono 31.506±0.033 24.90±00.04 + 0.82±00.00 1336.77±01.87
Lua/luajit 35.074±0.035 2.44±00.02 + 0.44±00.00 1399.61±01.60
Racket 36.947±0.162 92.71±00.16 + 0.00±00.00 1628.73±10.79
Haskell (MArray) 37.326±0.013 5.67±00.03 + 6.11±00.00 1513.15±08.31
D/dmd 37.466±0.010 3.45±00.03 + 1.00±00.03 1356.90±00.40
F#/.NET Core 38.363±0.057 37.86±00.05 + 2.10±00.01 1573.80±03.64
MLton 44.875±0.023 1.30±00.33 + 4.40±00.28 1941.05±19.16
Python/pypy 48.764±0.207 64.23±00.13 + 30.59±00.09 2076.08±25.96
Ruby/truffleruby (--jvm) 80.275±0.588 353.40±01.09 + 500.07±40.27 3327.63±27.96
Ruby/truffleruby 81.176±0.481 298.34±00.74 + 257.92±09.34 3973.50±42.02
Haskell 186.181±0.556 5.58±00.06 + 30.55±00.00 8151.90±99.97

Base64

Testing base64 encoding/decoding of the large blob into the newly allocated buffers.

Base64

Language Time, s Memory, MiB Energy, J
C/gcc (aklomp) 0.101±0.000 2.10±00.02 + 0.00±00.00 4.83±00.05
C/clang (aklomp) 0.101±0.000 2.16±00.01 + 0.00±00.00 4.81±00.05
Rust 0.970±0.000 2.38±00.03 + 0.12±00.01 39.54±00.34
C/clang 0.997±0.000 2.09±00.02 + 0.00±00.00 37.34±00.26
C/gcc 1.010±0.000 2.11±00.03 + 0.00±00.00 37.86±00.12
D/ldc2 1.042±0.001 3.09±00.04 + 3.96±00.01 43.46±00.77
Nim/gcc 1.081±0.001 1.63±00.05 + 5.39±00.05 42.90±00.19
Nim/clang 1.094±0.001 1.90±00.04 + 5.29±00.03 43.77±00.20
V/clang 1.160±0.007 2.36±00.03 + 1.29±00.15 47.30±00.49
Crystal 1.181±0.002 3.49±00.04 + 1.45±00.01 52.75±00.34
V/gcc 1.205±0.003 2.37±00.03 + 1.24±00.03 49.50±00.32
Ruby (--jit) 1.384±0.001 270.92±00.07 + 67.47±00.05 53.89±00.29
Ruby 1.389±0.001 14.63±00.02 + 58.67±00.03 53.74±00.10
Java 1.520±0.012 39.39±00.04 + 262.48±23.42 62.01±00.87
Scala 1.603±0.003 65.19±00.12 + 326.86±15.35 68.76±00.66
Kotlin/JVM 1.635±0.002 42.55±00.07 + 249.61±00.86 69.68±00.77
Vala/gcc 1.643±0.001 5.46±00.04 + 0.19±00.04 63.47±00.70
Vala/clang 1.643±0.001 5.46±00.04 + 0.22±00.05 62.97±00.40
C++/clang++ (libcrypto) 1.715±0.002 5.10±00.11 + 0.65±00.03 69.12±00.99
C++/g++ (libcrypto) 1.715±0.004 5.64±00.07 + 0.66±00.03 69.34±00.49
Node.js 1.743±0.006 40.76±00.04 + 38.86±00.02 70.15±00.65
Perl (MIME::Base64) 1.791±0.000 14.70±00.08 + 0.16±00.03 70.22±00.07
Go 1.875±0.002 4.22±00.05 + 3.92±00.05 80.99±00.49
PHP 2.093±0.017 17.79±00.03 + 0.00±00.00 84.17±00.78
D/gdc 2.442±0.003 7.52±00.07 + 3.35±00.00 108.08±00.52
D/dmd 2.739±0.001 3.60±00.12 + 3.85±00.05 119.70±00.68
Python 2.837±0.002 10.36±00.03 + 0.55±00.06 112.86±00.30
Zig 3.067±0.002 1.45±00.04 + 0.00±00.00 122.43±00.62
F#/.NET Core 3.202±0.052 38.62±00.06 + 18.68±00.71 120.67±01.23
Python/pypy 3.581±0.002 64.67±00.11 + 31.23±00.04 156.54±00.94
Tcl 3.685±0.078 5.12±00.06 + 0.00±00.00 149.06±01.75
Go/gccgo 3.720±0.002 25.62±00.20 + 7.71±00.17 168.84±00.90
C#/.NET Core 3.726±0.053 34.67±00.08 + 19.67±01.47 137.24±01.33
C#/Mono 4.692±0.014 25.71±00.08 + 18.74±00.03 193.29±01.07
Julia 5.023±0.004 244.56±00.09 + 42.28±00.09 188.22±02.10
Ruby/truffleruby (--jvm) 5.072±0.012 347.27±07.42 + 168.12±27.78 234.49±01.53
Ruby/jruby 10.519±0.026 182.81±02.29 + 80.63±02.65 420.63±01.57
Perl (MIME::Base64::Perl) 13.790±0.053 16.12±00.07 + 0.31±00.04 573.08±04.60
Ruby/truffleruby 16.232±0.006 295.77±00.95 + 232.04±04.13 647.25±03.84

Json

Testing parsing and simple calculating of values from a big JSON file.

Few notes:

Json

Language Time, s Memory, MiB Energy, J
C++/g++ (simdjson On-Demand) 0.066±0.000 112.99±00.03 + 60.31±00.07 2.73±00.01
C++/clang++ (simdjson On-Demand) 0.067±0.000 112.43±00.04 + 60.36±00.00 2.77±00.02
C++/clang++ (DAW JSON Link NoCheck) 0.070±0.001 112.39±00.06 + 0.00±00.00 2.94±00.04
C++/g++ (DAW JSON Link NoCheck) 0.080±0.000 113.28±00.02 + 0.00±00.00 3.23±00.03
C++/g++ (DAW JSON Link) 0.081±0.000 113.21±00.08 + 0.00±00.00 3.41±00.02
C++/clang++ (DAW JSON Link) 0.096±0.000 112.46±00.03 + 0.00±00.00 3.93±00.01
Rust (Serde Custom) 0.106±0.000 111.64±00.02 + 0.00±00.00 4.42±00.04
Rust (Serde Typed) 0.107±0.000 111.64±00.02 + 11.52±00.08 4.48±00.03
C++/g++ (gason) 0.132±0.000 113.06±00.11 + 96.85±00.06 5.23±00.01
C++/g++ (simdjson DOM) 0.139±0.000 113.21±00.24 + 175.85±00.23 5.92±00.03
C++/clang++ (gason) 0.143±0.000 112.40±00.06 + 96.97±00.06 5.82±00.03
D/ldc2 (Mir Asdf DOM) 0.145±0.000 112.66±00.02 + 61.26±00.01 6.03±00.02
C++/clang++ (simdjson DOM) 0.146±0.000 112.47±00.03 + 177.15±00.00 6.27±00.02
C++/g++ (RapidJSON) 0.166±0.000 113.32±00.02 + 127.47±00.30 7.05±00.07
C++/clang++ (RapidJSON) 0.235±0.000 112.36±00.07 + 129.04±00.05 9.77±00.03
D/ldc2 (Mir Amazon's Ion DOM) 0.236±0.000 112.79±00.03 + 80.70±00.00 9.81±00.06
C++/g++ (RapidJSON Precise) 0.244±0.000 113.29±00.02 + 128.82±00.05 10.24±00.08
C++/clang++ (RapidJSON Precise) 0.314±0.000 112.47±00.04 + 129.00±00.03 13.49±00.06
C++/g++ (Boost.JSON) 0.396±0.000 113.32±00.04 + 435.82±00.06 16.56±00.02
C++/g++ (RapidJSON SAX) 0.404±0.001 113.05±00.01 + 0.00±00.00 16.62±00.05
Nim/clang (jsony) 0.414±0.000 111.40±00.04 + 42.97±00.11 17.73±00.19
C++/clang++ (Boost.JSON) 0.418±0.001 112.46±00.05 + 436.25±00.06 17.59±00.14
Nim/gcc (jsony) 0.422±0.000 111.10±00.04 + 42.84±00.14 17.75±00.15
C++/g++ (RapidJSON SAX Precise) 0.448±0.000 113.07±00.01 + 0.00±00.00 19.27±00.06
Go (jsoniter) 0.520±0.002 231.00±00.12 + 1.24±00.08 22.19±00.12
C++/clang++ (RapidJSON SAX) 0.531±0.000 194.70±00.04 + 0.00±00.00 20.74±00.17
Node.js 0.546±0.006 150.03±00.06 + 188.93±00.13 25.76±00.18
Java (DSL-JSON) 0.619±0.012 259.64±00.07 + 188.73±08.78 31.78±00.67
V/gcc 0.633±0.001 111.91±00.05 + 496.18±00.09 26.27±00.15
Rust (Serde Untyped) 0.639±0.001 111.61±00.03 + 840.27±00.03 25.87±00.18
V/clang 0.639±0.000 111.97±00.03 + 496.24±00.03 26.66±00.17
C++/clang++ (RapidJSON SAX Precise) 0.663±0.000 194.66±00.03 + 0.00±00.00 26.73±00.14
Python/pypy 0.671±0.002 284.89±00.05 + 125.41±00.04 29.24±00.15
Crystal (Pull) 0.687±0.005 113.42±00.04 + 18.47±00.03 30.07±00.17
Crystal (Schema) 0.704±0.002 113.40±00.02 + 48.88±00.03 30.82±00.16
C#/.NET Core (System.Text.Json) 0.755±0.001 479.22±00.04 + 138.55±00.00 32.96±00.31
Zig 0.773±0.000 110.75±00.01 + 11.98±00.06 30.65±00.20
Julia (JSON3) 0.818±0.005 452.44±00.58 + 212.54±02.91 33.11±00.26
Perl (Cpanel::JSON::XS) 0.834±0.009 125.32±00.10 + 402.87±00.02 34.85±00.42
Go 0.856±0.001 117.22±00.02 + 79.73±00.22 35.32±00.31
Crystal 0.937±0.005 113.52±00.08 + 392.53±00.03 42.18±00.34
PHP 0.982±0.002 126.96±00.04 + 682.21±00.00 40.85±00.23
Nim/clang (Packedjson) 0.991±0.002 112.15±00.02 + 294.42±00.00 40.83±00.21
Nim/gcc (Packedjson) 1.010±0.001 111.83±00.03 + 294.42±00.00 41.89±00.21
C++/clang++ (json-c) 1.194±0.007 112.71±00.07 + 1216.11±00.03 50.61±00.93
C++/g++ (json-c) 1.198±0.006 113.43±00.04 + 1215.96±00.00 50.29±00.65
Clojure 1.199±0.019 464.27±05.08 + 541.31±49.27 61.77±00.48
Go/gccgo 1.259±0.003 138.89±00.04 + 83.65±00.10 53.56±00.15
C#/.NET Core 1.283±0.013 486.95±00.07 + 294.45±00.04 55.84±00.54
C++/clang++ (Nlohmann) 1.297±0.002 112.59±00.05 + 360.20±00.00 54.81±00.28
Nim/gcc 1.345±0.002 111.87±00.04 + 919.93±00.00 56.30±00.21
Nim/clang 1.351±0.004 112.15±00.01 + 925.03±00.00 55.67±00.23
Ruby (--jit) 1.448±0.007 380.59±00.07 + 263.15±00.02 61.92±00.27
Ruby 1.449±0.003 123.97±00.02 + 263.11±00.01 61.61±00.15
CPython (UltraJSON) 1.454±0.003 122.26±00.13 + 545.52±01.28 54.11±00.21
C++/g++ (Nlohmann) 1.489±0.008 113.32±00.03 + 447.92±00.04 60.89±00.57
Python 1.524±0.002 120.30±00.07 + 375.25±00.03 60.10±00.20
F#/.NET Core (System.Text.Json) 1.777±0.004 486.91±00.03 + 345.26±00.13 77.46±00.66
Ruby (YAJL) 1.962±0.010 123.89±00.04 + 282.64±00.07 82.95±00.75
Scala (uPickle) 1.997±0.014 292.25±00.16 + 702.97±67.44 97.94±00.61
D/ldc2 2.079±0.003 112.90±00.05 + 680.22±00.05 86.04±00.27
C#/Mono 2.306±0.027 252.32±00.07 + 31.57±00.02 97.12±00.89
Haskell 2.590±0.005 117.60±00.03 + 713.50±00.38 110.05±01.10
Rust (jq) 2.804±0.003 113.77±00.06 + 779.44±00.39 116.12±00.64
Ruby/jruby 2.998±0.038 442.51±05.84 + 930.50±130.38 151.53±02.51
C++/clang++ (Boost.PropertyTree) 3.158±0.003 194.88±00.03 + 1232.84±00.06 131.20±00.85
C++/g++ (Boost.PropertyTree) 3.341±0.009 113.17±00.03 + 1440.16±00.03 139.24±00.94
Vala/gcc 3.613±0.008 114.75±00.06 + 940.52±00.09 155.10±01.78
Vala/clang 3.613±0.014 114.75±00.03 + 940.56±00.09 153.78±01.48
D/gdc 3.656±0.008 116.62±00.05 + 681.22±00.10 156.04±00.72
D/dmd 4.534±0.004 113.23±00.04 + 680.46±00.04 181.45±00.78
Perl (JSON::Tiny) 9.712±0.100 125.59±00.03 + 529.02±00.02 427.10±03.42
Ruby/truffleruby (--jvm) 14.091±0.265 477.27±14.72 + 2545.17±68.47 912.67±20.03
Ruby/truffleruby 24.040±0.350 433.56±02.08 + 2561.27±48.17 1194.76±20.42

Matmul

Testing allocating and multiplying matrices.

Matmul

Language Time, s Memory, MiB Energy, J
D/ldc2 (lubeck) 0.043±0.000 5.84±00.04 + 57.97±00.13 4.42±00.02
Nim/gcc (Arraymancer) 0.063±0.006 4.69±00.01 + 58.04±00.15 5.21±00.52
Python (NumPy) 0.067±0.000 30.06±00.12 + 58.10±00.03 6.29±00.03
C++/clang++ (Eigen) 0.071±0.003 38.76±05.62 + 51.51±05.67 5.87±00.10
C++/g++ (Eigen) 0.076±0.003 19.72±13.35 + 70.30±13.23 5.60±00.15
Java (ND4J) 0.078±0.001 105.22±01.56 + 92.03±00.12 6.13±00.06
Nim/clang (Arraymancer) 0.081±0.012 6.19±00.07 + 57.45±00.14 6.87±00.69
Rust (ndarray) 0.090±0.001 2.24±00.04 + 68.74±00.05 6.11±00.07
Julia (threads: 2) 0.101±0.000 265.20±00.47 + 46.43±00.13 5.91±00.02
Julia (threads: 1) 0.151±0.000 265.55±00.25 + 45.95±00.09 7.30±00.08
Julia (no BLAS) 1.041±0.012 243.90±00.24 + 51.54±00.04 46.04±00.54
D/ldc2 1.715±0.002 3.17±00.02 + 70.49±00.03 63.20±00.18
D/gdc 1.870±0.002 6.81±00.06 + 70.97±00.03 73.21±00.21
D/dmd 1.874±0.002 3.42±00.02 + 70.48±00.01 71.16±00.16
C/gcc 3.029±0.000 1.50±00.02 + 68.74±00.04 111.52±00.91
Vala/clang 3.060±0.001 3.93±00.08 + 69.88±00.07 105.78±00.97
C/clang 3.062±0.000 1.51±00.01 + 68.73±00.03 104.53±00.17
Rust 3.064±0.001 2.02±00.04 + 68.88±00.07 104.85±00.19
Zig 3.085±0.001 1.40±00.02 + 68.89±00.00 109.21±00.14
Nim/gcc 3.089±0.002 2.51±00.03 + 66.26±00.00 114.20±00.48
Java 3.089±0.001 38.29±00.04 + 68.54±00.13 109.95±00.09
Swift 3.096±0.000 6.55±00.03 + 68.91±00.01 110.89±01.35
Nim/clang 3.121±0.001 2.78±00.01 + 66.00±00.00 107.00±00.38
Vala/gcc 3.125±0.001 3.95±00.03 + 69.91±00.04 114.45±00.11
Go 3.152±0.000 3.70±00.04 + 73.19±00.09 115.16±01.26
Crystal 3.160±0.001 3.78±00.05 + 59.96±00.01 115.82±00.30
Go/gccgo 3.160±0.001 24.82±00.03 + 73.40±00.05 112.08±00.21
V/gcc 3.188±0.001 2.53±00.12 + 70.90±00.00 120.57±00.24
V/clang 3.194±0.001 2.89±00.03 + 70.90±00.00 120.75±00.24
Node.js 3.208±0.001 45.17±00.06 + 70.61±00.00 129.36±00.17
Python/pypy 3.268±0.002 65.50±00.07 + 68.63±00.04 135.95±00.19
Scala 3.334±0.004 66.21±00.12 + 147.70±00.19 122.19±00.14
Kotlin/JVM 3.680±0.003 40.47±00.06 + 68.25±00.27 153.89±00.35
C#/.NET Core 4.874±0.000 34.59±00.03 + 69.33±00.00 195.95±00.22
C#/Mono 7.413±0.000 25.43±00.10 + 69.52±00.02 302.00±03.34
Ruby/truffleruby 16.489±2.861 366.34±03.56 + 447.40±65.47 625.65±94.01
Ruby/truffleruby (--jvm) 25.232±0.159 460.71±32.48 + 446.25±62.62 903.31±14.59
Ruby 199.779±1.180 14.88±00.07 + 69.07±00.02 8676.55±45.16
Ruby (--jit) 202.181±2.040 271.47±00.04 + 69.06±00.02 8655.57±187.67
Perl 222.566±1.469 9.40±00.08 + 599.71±00.03 9015.71±75.12
Python 280.771±2.283 10.62±00.07 + 69.09±00.06 11178.73±44.71
Tcl 334.061±2.020 7.35±00.06 + 400.18±00.00 13954.09±93.63
Ruby/jruby 389.418±5.069 268.52±02.25 + 709.04±17.44 16350.68±256.43

Primes

Testing:

  • generating primes using the optimized sieve of Atkin;
  • prefix search for their decimal numbers using Trie data structure.

Notes:

  • All languages but V and Python use unordered hashmaps (V and Python don't provide those out of box, and their hashmaps use keys in the insertion order);
  • The results are always sorted (could be unstable or stable though).

Primes

Language Time, s Memory, MiB Energy, J
Zig 0.059±0.000 0.92±00.01 + 48.53±00.03 2.45±00.02
Crystal 0.122±0.000 2.98±00.03 + 90.71±00.17 5.52±00.08
Rust 0.140±0.000 0.94±00.01 + 74.26±00.07 5.35±00.05
Java 0.159±0.002 38.27±00.10 + 153.79±03.78 8.89±00.06
C++/g++ 0.189±0.000 2.70±00.90 + 116.66±00.81 7.76±00.05
C++/clang++ 0.198±0.000 1.66±00.02 + 87.96±00.02 7.79±00.09
V/clang 0.212±0.001 1.91±00.05 + 203.15±01.44 8.46±00.06
Node.js 0.227±0.002 39.10±00.03 + 150.29±00.26 11.37±00.12
V/gcc 0.240±0.001 2.28±00.14 + 219.14±00.67 9.66±00.12
Nim/clang 0.297±0.001 2.07±00.01 + 601.73±02.96 11.72±00.09
Lua/luajit 0.338±0.002 1.20±00.02 + 157.12±01.04 13.22±00.05
Nim/gcc 0.352±0.003 1.68±00.07 + 614.62±00.26 13.48±00.20
Scala 0.362±0.006 67.43±00.09 + 248.88±11.36 18.63±00.35
Julia 0.597±0.001 246.42±00.24 + 374.41±01.06 23.23±00.15
Python/pypy 0.880±0.002 63.32±00.09 + 250.27±00.06 34.53±00.42
Ruby/truffleruby (--jvm) 1.381±0.026 354.60±10.97 + 552.99±34.23 90.57±01.36
Ruby (--jit) 1.442±0.004 270.43±00.06 + 147.02±00.05 59.14±00.99
Lua 1.478±0.004 2.28±00.01 + 283.04±00.48 57.46±00.33
Ruby/truffleruby 1.506±0.007 294.80±00.82 + 410.90±26.05 84.20±00.88
Ruby/jruby 1.990±0.057 182.28±01.67 + 538.37±28.70 102.14±03.48
Ruby 2.057±0.005 13.87±00.07 + 147.07±00.04 82.80±00.47
Python 5.022±0.024 10.49±00.04 + 234.72±00.26 196.62±02.52

Tests Execution

Environment

CPU: Intel(R) Xeon(R) E-2324G

Base Docker image: Debian GNU/Linux bookworm/sid

Language Version
.NET Core 6.0.401
C#/.NET Core 4.3.0-3.22415.1 (8301d484)
C#/Mono 6.8.0.105
Chez Scheme 9.5.4
Clojure "1.11.1"
Crystal 1.5.1
D/dmd v2.100.2
D/gdc 12.2.0
D/ldc2 1.30.0
Elixir 1.12.2
F#/.NET Core 12.0.4.0 for F# 6.0
Go go1.19.1
Go/gccgo 12.2.0
Haskell 9.4.2
Java 19
Julia v"1.8.1"
Kotlin 1.7.10
Lua 5.4.4
Lua/luajit 2.1.0-beta3
MLton 20210117
Nim 1.6.6
Node.js v18.9.0
OCaml 4.14.0
PHP 8.1.5
Perl v5.34.0
Python 3.10.7
Python/pypy 7.3.9-final0 for Python 3.9.12
Racket "8.6"
Ruby 3.1.2p20
Ruby/jruby 9.3.8.0
Ruby/truffleruby 22.2.0
Rust 1.64.0
Scala 3.2.0
Swift 5.7
Tcl 8.6
V 0.3.1 993802f
Vala 0.56.3
Zig 0.9.1
clang/clang++ 14.0.6
gcc/g++ 12.2.0

Using Docker

Build the image:

$ docker build docker/ -t benchmarks

The pinned packages could be missing, in that case please update them with:

$ ./run.sh update_apt

Run the image:

$ docker run -it --rm -v $(pwd):/src benchmarks <cmd>

where <cmd> is:

  • versions (print installed language versions);
  • shell (start the shell);
  • brainfuck bench (build and run Brainfuck bench.b benchmarks);
  • brainfuck mandel (build and run Brainfuck mandel.b benchmarks);
  • base64 (build and run Base64 benchmarks);
  • json (build and run Json benchmarks);
  • matmul (build and run Matmul benchmarks);
  • primes (build and run Primes benchmarks);

Please note that the actual measurements provided in the project are taken semi-manually (via shell) as the full update takes days and could have occassional issues in Docker.

There is a ./run.sh that could be used to simplify Docker usage:

  • ./run.sh build (build the image);
  • ./run.sh make versions (run the image with the versions command);
  • sudo ./run.sh shell (run the image with the `shell' command, sudo is required to read energy levels).

Manual Execution

Makefiles contain recipes for building and executing tests with the proper dependencies. Please use make run (and make run2 where applicable). The measurements are taken using analyze.rb script:

$ cd <test suite>
$ ../analyze.rb make run
$ ../analyze.rb make run[<single test>]

Please note that the measurements could take hours. It uses 10 iterations by default, but it could be changed using ATTEMPTS environment variable:

$ ATTEMPTS=1 ../analyze.rb make run

Prerequisites

Please use Dockerfile as a reference regarding which packages and tools are required.

For all (optional):

  • Powercap for reading energy counters in Linux (Debian package powercap-utils).

For Python:

  • NumPy for matmul tests (Debian package python3-numpy).
  • UltraJSON for JSON tests (Debian package python3-ujson).

For C++:

  • Boost for JSON tests (Debian package libboost-dev).
  • JSON-C for JSON tests (Debian package libjson-c-dev).

For Rust:

  • libjq for jq test (Debian packages libjq-dev, libonig-dev and environment variable JQ_LIB_DIR=/usr/lib/x86_64-linux-gnu/).

For Java, Scala:

  • Coursier for downloading Maven artifacts.

For Haskell:

  • network for TCP connectivity between the tests and the test runner.
  • raw-strings-qq for raw string literals used in tests.

For Perl:

  • cpanminus for installing modules from CPAN (Debian package cpanminus).

For Vala:

  • JSON-GLib for JSON tests (Debian package libjson-glib-dev).

Contribution

Please follow the criteria specified in the overview. Besides that please ensure that the communication protocol between a test and the test runner is satisfied:

  • The test runner listens on localhost:9001;
  • All messages are sent using TCP sockets closed immediately after the message has been sent;
  • There are two messages sent from a test (it establishes the measurement boundary):
    1. The beginning message having the format name of the test/tprocess ID (the process ID is used to measure the memory consumption). Please note that the name of the test couldn't use Tab character as it's a delimiter;
    2. The end message with any content (mostly it's "stop" for consistency).
  • The test runner could be unavailable (if the test is launched as is) and the test should gracefully handle it.

Makefile guide

Binary executables

If the test is compiled into a single binary, then two sections of the Makefile require changes:

  • append a new target (the final binary location) into executables variable;
  • append the proper target rule.

Compiled artifacts

If the test is compiled, but can't be executed directly as a binary, then three sections of the Makefile require changes:

  • append a new target (the final artifact location) into artifacts variable;
  • append the proper target rule to compile the test;
  • append run[<target_artifact>] rule to run the test.

Scripting language

If the test doesn't require compilation, then two sections of the Makefile requires changes:

  • append run[<script_file>] into all_runners variable;
  • append run[<script_file>] rule to run the test.

README update

TOC is regenerated using git-markdown-toc:

./run.sh toc

Docker image update

Debian packages are pinned and updated with the script (first, please ensure that the image is fine with the linter):

./run.sh lint
./run.sh update_apt

About

Some benchmarks of different languages

License:MIT License


Languages

Language:Makefile 9.2%Language:C++ 8.2%Language:Ruby 5.5%Language:Rust 4.8%Language:Java 4.7%Language:Zig 4.6%Language:C# 4.1%Language:C 3.9%Language:Lua 3.8%Language:D 3.4%Language:Nim 3.1%Language:Vala 2.9%Language:JavaScript 2.8%Language:Python 2.8%Language:Perl 2.8%Language:Brainfuck 2.7%Language:Haskell 2.6%Language:Scala 2.6%Language:Julia 2.5%Language:Crystal 2.4%Language:V 2.3%Language:F# 2.2%Language:Tcl 2.2%Language:Go 2.0%Language:Racket 1.9%Language:Dockerfile 1.9%Language:Kotlin 1.6%Language:Swift 1.6%Language:Standard ML 1.1%Language:Scheme 1.0%Language:OCaml 0.8%Language:Elixir 0.8%Language:PHP 0.7%Language:Shell 0.4%Language:Clojure 0.3%