This project explores the use of asynchronous exceptions as an inter-thread
communication mechanism in GHC Haskell. We implemented the actor model of
programming on top of asynchronous exceptions as a small framework:
a send function and a message-receipt mainloop (to be run on each thread).
The paper (main.lhs) is written as a Literate-Haskell program and was
accepted at Haskell Symposium 2023. To read the paper, we recommend rendering
it first or visiting https://doi.org/10.1145/3609026.3609728.
-
We developed this program on NixOS, and recommend using
nix-shellto enter an environment where themakefiledoes the rest.nix-shell --run 'make'ornix-build-- Build the papernix-shell --run 'make main.bench.elf'ornix-build-- Build the benchmark executablenix-shell --run 'make bench'-- Build and run the benchmark (first read all of Benchmark the program)nix-shell --run 'make prof'-- Obtain an eventlog
-
For users not on NixOS, we include a cabal-file and a cabal-freeze-file. We built the project on GHC
9.0.2withbase-4.15.1.0using Cabal3.10.1.0.$ cabal update ... $ cabal v2-build ... Linking /.../hakkell.paper/dist-newstyle/build/x86_64-linux/ghc-9.0.2/hakkell-paper-0.0.0/x/main/build/main/main ... $ cabal v2-exec make main.bench.elf ... [1 of 1] Compiling Main ( main.noprint.lhs, main.noprint.o ) Linking main.bench.elf ... rm main.noprint.lhs
The
makefileisn't aware of thecabal execenvironment and some targets have additional dependencies, so not all the targets will work undercabal exec(the clean targets do not work, for example).
Make sure to use send and run in your programs. The other functions
(sendStatic, runStatic, and runDyn) aren't meant to be used directly.
The main method supports two modes of operation.
For either mode, set the environment variable RING_SIZE
to determine how many nodes will participate in the election.
-
Set the environment variable
MODEtoactors,channels, orcontrolto runbenchActors,benchChannels, orbenchControlonce, on the specifiedRING_SIZEnodes.This is the mode we used for measuring total bytes allocated.
-
If the environment variable
MODEis not set, then the criterion benchmark will run. It sets up a benchmark group for the specifiedRING_SIZEcontaining a becnhmark ofbenchControl,benchActors, andbenchChannels.This is the mode we used for measuring running time. We used a shell script that provided command-line arguments interpreted by criterion to select and run only one of those functions at a time.
An extra step is required to obtain a consistent result from benchmark mode (above). Printlines must be stripped from the source code. The included makefile has targets which attempt to control for this and other factors that may confound benchmark results.
-
make main.bench.elf- This target uses a python script to remove printlines from
main.lhsand compiles an executable which defaults to+RTS -N4.- You may override the capabilities default with an environment variable.
For example, an
+RTS -Ndefault is obtained this way:
env CAPABILITIES= make main.bench.elformake main.bench.elf CAPABILITIES=
- You may override the capabilities default with an environment variable.
For example, an
- Running executables produced by this target is sufficient to get a consistent result on Amazon AWS EC2 instances.
- This target uses a python script to remove printlines from
-
make bench- This target builds an executable and performs additional steps before
running benchmark mode.
- It attempts to control for various factors on a personal laptop running linux that may confound benchmark results.
- It executes
benchprep.shto set your CPU to 1.6GHz, turns off frequency scaling, stops TLP & ThermalD, and disables Intel Pstate. - If you run
make bench, first auditbenchprep.shor zero it out.
- The output from
make benchismake.bench.csvandmake.bench.html.
- This target builds an executable and performs additional steps before
running benchmark mode.