Skip to content

utahplt/chorex_benchmarks

Repository files navigation

ChorexBenchmarks

Performance benchmarks for [Chorex](https://github.com/utahplt/chorex)

Synopsis

bash$ iex -S mix
iex> ChorexBenchmarks.stats()

Description

You will need a recent version of Elixir (1.18 or better is best) and at least Perl 5.36 (only if re-running bench_maker.pl) to use this.

To run the benchmarks:

  1. Clone this repo.
  2. Get the dependencies (Chorex and Benchee) with mix deps.get.
  3. (Optional) Run perl bench_maker.pl. This will recreate the big_chor.ex file if needed.
  4. Fire up iex -S mix. This takes several seconds as the big_chor.ex file seems to take a while to compile.
  5. Run the benchmarks with ChorexBenchmarks.stats(). This takes about 3 minutes.

Results

By far the most punishing benchmarks are those where there are nested recursive try blocks. A structure like:

def loop(...) do
  try do
    ...
    loop(...)
  rescue
    ...
  end
end

is extremely punishing as the stack gets deeper and deeper. This can be seen in the Miniblock and Deep Loops benchmarks. In contrast, a structure where the try is not involved in the recursion, like in Flat Loops, the performance is much better:

def loop(...) do
  do_work(...)
  loop(...)
end

def do_work(...) do
  try do
    ...
  rescue
    ...
  end
end

Finally, try/rescue seems to impose a negligible impact when there are a large number (100) of actors. Since these actors are specified manually, and Chorex does not yet have census polymorphism, 100 seems to be a reasonable torture test for a choreography.

Benchmark data

Operating System: macOS
CPU Information: Apple M1 Pro
Number of Available Cores: 10
Available memory: 32 GB
Elixir 1.18.0
Erlang 27.2
JIT enabled: true

Miniblock

Nameipsaveragedeviationmedian99th %
miniblock: without try block1.42 K0.71 ms±35.00%0.70 ms0.78 ms
miniblock: with try block0.147 K6.80 ms±13.09%6.58 ms8.91 ms

Comparison

Nameipsslowdown
miniblock: without try block1.42 K
miniblock: with try block0.147 K9.65× slower +6.10 ms

Flat Loops

1,000 iterations

Nameipsaveragedeviationmedian99th %
flat loop with try, 1000 iterations3.80263.16 ms±4.74%258.63 ms296.86 ms
flat loop without try, 1000 iterations3.79264.09 ms±8.35%273.21 ms285.60 ms

Comparison

Nameipsslowdown
flat loop with try, 1000 iterations3.80
flat loop without try, 1000 iterations3.791.00× slower +0.93 ms

10,000 iterations

Nameipsaveragedeviationmedian99th %
flat loop without try, 10000 iterations0.372.74 s±0.24%2.74 s2.75 s
flat loop with try, 10000 iterations0.342.92 s±0.10%2.92 s2.93 s

Comparison

Nameipsslowdown
flat loop without try, 10000 iterations0.37
flat loop with try, 10000 iterations0.341.07× slower +0.186 s

Deep Loops

100 iterations

Nameipsaveragedeviationmedian99th %
loop: no try, 100 iterations, no split work47.4121.09 ms±0.85%21.09 ms21.65 ms
loop: no try, 100 iterations, split work47.3921.10 ms±0.84%21.10 ms21.59 ms
loop: with try, 100 iterations, no split work41.7323.96 ms±15.59%23.70 ms25.95 ms
loop: with try, 100 iterations, split work40.5424.67 ms±2.35%24.53 ms26.57 ms

Comparison

Name
loop: no try, 100 iterations, no split work47.41
loop: no try, 100 iterations, split work47.391.00× slower +0.0106 ms
loop: with try, 100 iterations, no split work41.731.14× slower +2.87 ms
loop: with try, 100 iterations, split work40.541.17× slower +3.57 ms

1,000 iterations

Nameipsaveragedeviationmedian99th %
loop: no try, 1000 iterations, split work4.76210.27 ms±0.36%210.17 ms214.66 ms
loop: no try, 1000 iterations, no split work4.75210.34 ms±0.28%210.34 ms212.55 ms
loop: with try, 1000 iterations, no split work2.21452.92 ms±9.89%455.50 ms541.35 ms
loop: with try, 1000 iterations, split work2.20455.05 ms±9.61%454.87 ms541.07 ms

Comparison

Nameipsslowdown
loop: no try, 1000 iterations, split work4.76
loop: no try, 1000 iterations, no split work4.751.00× slower +0.0657 ms
loop: with try, 1000 iterations, no split work2.212.15× slower +242.64 ms
loop: with try, 1000 iterations, split work2.202.16× slower +244.77 ms

10,000 iterations

Nameipsaveragedeviationmedian99th %
loop: no try, 10000 iterations, split work0.501.98 s±0.22%1.98 s1.99 s
loop: no try, 10000 iterations, no split work0.501.99 s±0.85%1.98 s2.03 s
loop: with try, 10000 iterations, no split work0.025838.83 s±0.00%38.83 s38.83 s
loop: with try, 10000 iterations, split work0.022544.54 s±0.00%44.54 s44.54 s

Comparison

Nameipsslowdown
loop: no try, 10000 iterations, split work0.50
loop: no try, 10000 iterations, no split work0.501.00× slower +0.00480 s
loop: with try, 10000 iterations, no split work0.025819.57× slower +36.84 s
loop: with try, 10000 iterations, split work0.022522.46× slower +42.56 s

State Machine

Nameipsaveragedeviationmedian99th %
state machine no try1.99 K503.74 μs±816.82%476.71 μs759.63 μs
state machine with try1.97 K506.92 μs±35.77%510.54 μs816.90 μs
state machine with try & recovery1.96 K509.54 μs±36.43%508.38 μs824.76 μs

Comparison

Nameipsslowdown
state machine no try1.99 K
state machine with try1.97 K1.01× slower +3.18 μs
state machine with try & recovery1.96 K1.01× slower +5.80 μs

Lots of Actors

Nameipsaveragedeviationmedian99th %
lots of actors, no try141.167.08 ms±37.15%6.49 ms18.54 ms
lots of actors, with try139.987.14 ms±38.32%6.44 ms18.31 ms

Comparison

Nameipsslowdown
lots of actors, no try141.16
lots of actors, with try139.981.01× slower +0.0598 ms

Compile times

Run the bench_maker.pl script to create some big Elixir files:

perl bench_maker.pl 10 > big_chor_10.ex
perl bench_maker.pl 100 > big_chor_100.ex
perl bench_maker.pl 1000 > big_chor_1000.ex

Now compile everything and use the compile profiler to get compile times:

mix compile --force --profile time

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published