Awesome
GpioTwiddler
This is a simple Nerves application for the BeagleBone Black that is used to measure the performance of various ways of toggling a GPIO. This is useful to demonstrate tradeoffs and set expectations for performance in real applications.
Please, please realize that many of the options compared are not identical. While they all toggle a GPIO, some are platform dependent, require the Erlang VM to run as root, run the risk of crashing the VM, can't support other GPIO features (like notification when an input changes), or require C coding. TL;DR: The more of these issues or limitations you can put up with, the faster things go. Old 16 MHz 8-bit microcontrollers are better suited to some tasks.
Naming
Data for each experiment is named with the following convention:
kernel_erlang_work_test.csv
kernel
is one of the following:
rt
- Linux kernel compiled with CONFIG_PREEMPT_RT_FULL, HZ=250ll
- Linux kernel compiled with CONFIG_PREEMPT_LL (low-latency desktop), HZ=250
erlang
is one of the following:
smp
- Erlang compiled with SMP enablednosmp
- Erlang compiled with SMP disabled
work
is one of the following:
idle
- Nothing else is going on. The twiddler has 100% of the CPU.timer
- AGenServer
gets a timer event sent to it every 1 ms.stress
- The Cstress
program is started and instructed to max out the CPU.estress
- An Elixir process is started that computes square roots constantly (similar tostress
, but in Elixir)estress2
- Same asestress
, but the twiddler runs at the Erlanghigh
priority level.GpioTwiddler.Stress
runs at thenormal
priority level.
test
is one of the following:
ale
-GpioTwiddler.Ale.twiddle
elixirwrite
- Use sysfs viaIO.write/2
in normal mode.GpioTwiddler.Elixir.twiddle(20000, [], :write)
elixirbinwrite
- Use sysfs viaIO.binwrite/2
in normal mode.GpioTwiddler.Elixir.twiddle(20000, [], :binwrite)
elixirrawbinwrite
- Use sysfs viaIO.binwrite/2
in raw mode.GpioTwiddler.Elixir.twiddle(20000, [:raw], :binwrite)
erlangwrite
- Use sysfs via:file.write/2
in normal mode.GpioTwiddler.Erlang.twiddle(20000)
erlangrawwrite
- Use sysfs via:file.write/2
in raw mode.GpioTwiddler.Erlang.twiddle_raw(20000)
sysfs
- Use sysfs in C.GpioTwiddler.C.sysfs(20000)
mmap
- Use mmap in C.GpioTwiddler.C.mmap(20000)
nif
- Use mmap via a NIF.GpioTwidder.Nif.twiddle(20000)
nifenum
- Use mmap via a NIF, but in Elixir iterate usingEnum.each
.GpioTwiddler.Nif.twiddle_enum(20000)
The filename arduino-uno-r3
is for captures using an Arduino Uno R3 running
the code in arduino/twiddle_fast
.
Results
Replicating the results
Assuming that you have a BeagleBone Black, run through the Nerves installation guide to set up your system.
Build an SDCard image by running:
mix deps.get
mix firmware
Then insert a MicroSD card into a reader on your computer and run mix firmware.burn
.
After burning the MicroSD card, place it in the BBB and boot. You'll be presented
with an Elixir shell prompt on the serial port. All tests toggle Pin 12 on
connector P9 on the BBB. Hook up a logic analyzer to measure this. See the
individual modules for tests, but you can try one or more of the following:
GpioTwiddler.Ale.twiddle 10000
- toggle using elixir_aleGpioTwiddler.Elixir.twiddle 10000
- toggle using pure Elixir codeGpioTwiddler.Erlang.twiddle 10000
- toggle using Erlang standard library calls directlyGpioTwiddler.Nif.twiddle 10000
- toggle using a NifGpioTwiddler.C.sysfs 10000
- toggle in C using the Linux sysfs interfaceGpioTwiddler.C.mmap 10000
- toggle in C using mmap