This sketch measures the amount of time consumed by the AceButton::check()
method when processing various button events. It uses a special
ProfilingButtonConfig
object that allows the program to inject button events
into the library. The profiling numbers come from activating the TimingStats
object that has been instrumented into the AceButton::check()
method.
Note that ProfilingButtonConfig
class generates synthetic button events,
bypassing the actual digitalRead()
function. The digitalRead()
function on
an Arduino AVR platform (UNO, Nano, etc) is
known to be slow
which will add to the timing values shown below in actual usage.
The digitalWriteFast library
might be an alternative if speed is critical.
Version: AceButton v1.10.0
DO NOT EDIT: This file was auto-generated using make README.md
.
This program depends on the following libraries:
This requires the AUniter script to execute the Arduino IDE programmatically.
The Makefile
has rules to generate the *.txt
results file for several
microcontrollers that I usually support, but the $ make benchmarks
command
does not work very well because the USB port of the microcontroller is a
dynamically changing parameter. I created a semi-automated way of collect the
*.txt
files:
- Connect the microcontroller to the serial port. I usually do this through a USB hub with individually controlled switch.
- Type
$ auniter ports
to determine its/dev/ttyXXX
port number (e.g./dev/ttyUSB0
or/dev/ttyACM0
). - If the port is
USB0
orACM0
, type$ make nano.txt
, etc. - Switch off the old microcontroller.
- Go to Step 1 and repeat for each microcontroller.
The generate_table.awk
program reads one of *.txt
files and prints out an
ASCII table that can be directly embedded into this README.md file. For example
the following command produces the table in the Nano section below:
$ ./generate_table.awk < nano.txt
Fortunately, we no longer need to run generate_table.awk
for each *.txt
file. The process has been automated using the generate_readme.py
script which
will be invoked by the following command:
$ make README.md
The CPU times below are given in microseconds. The "samples" column is the
number of TimingStats::update()
calls that were made.
v1.8.1
- Add benchmarks for STM32.
v1.8.3
- Upgrade the ESP32 Arduino Core from v1.0.4 to v1.0.6.
- Most things remain the same, maybe slightly faster, except for
LadderButtonConfig
. The flash memory consumption goes up by about 14kB, and the CPU time forLadderButtonConfig::checkButtons()
goes up significantly, from 24 micros on average to 67 micros. It looks like they changed the implementation ofanalogRead()
in v1.0.5. See espressif/arduino-esp32#4973 and espressif/arduino-esp32#3377.
- Most things remain the same, maybe slightly faster, except for
v1.9
- Add benchmarks for
ButtonConfigFast1<>
,ButtonConfigFast2<>
, andButtonConfigFast3<>
, using one of the<digitalWriteFast.h>
libraries for AVR processors.- The primary motivation of using
<digitalWriteFast.h>
is the 100-500 byte reduction in flash memory consumption. - As a bonus, the
AceButton::check()
call becomes faster. Comparing the numbers forEncoded4To2ButtonConfig
andButtonConfigFast3
, both perform 3 calls toAceButton::check()
, butButtonConfigFast3
makes those calls almost twice as fast asEncoded4To2ButtonConfig
(38 microseconds versus 72 microseconds).
- The primary motivation of using
v1.9.1
- Upgrade STM32duino Core from 1.9.0 to 2.0.0.
- Upgrade SparkFun SAMD Core from 1.8.1 to 1.8.3.
- No significant change in CPU times.
v1.9.2
- Remove SAMD21 since I can no longer flash them using latest tool chain.
- Upgrade various tool chains:
- Arduino IDE from 1.8.13 to 1.8.19
- Arduino CLI to 0.20.2
- Arduino AVR from 1.8.3 to 1.8.4
- STM32duino from 2.0.0 to 2.2.0
- ESP8266 from 2.7.4 to 3.0.2
- ESP32 from 1.0.6 to 2.0.2
- Teensyduino from 1.53 to 1.56
- No significant changes except for LadderButtonConfig:
- ESP8266 3.0.2: significantly faster (150 micros to 91 micros).
- ESP32 2.0.2: significantly slower (68 micros to 91 micros)
- Probably due to implementation changes of the underlying
analogRead()
function.
v1.10.0
- Boards
- Add SAMD21, using Seeed XIAO M0.
- Add SAMD51, using Adafruit ItsyBitsy M4.
- Remove Teensy 3.2.
- Tool chain
- Arduino CLI to 0.31.0
- Arduino AVR 1.8.6
- Update ESP32 to 2.0.9
- Update STM32duino 2.5.0
- Add Seeeduino SAMD 1.8.4
- Add Adafruit SAMD 1.7.11
- Add
kEventHeartBeat
.- Increases CPU time by a few microseconds or less if you squint hard enough.
- Increases
sizeof(AceButton)
by 3 bytes to 17 on AVR processors, by 4 bytes to 20 on 32-bit processors. - Increases
sizeof(ButtonConfig)
by 2 bytes to 18 on AVR processors`, no change on 32-bit processors due to padding in struct.
The following table shows the minimum, average, and maximum (min/avg/max) time taken for a number of scenarios in units of microseconds:
- idle
- one
AceButton::check()
call with no button events
- one
- press/release
- one
AceButton::check()
call with Press and Release events
- one
- click
- one
AceButton::check()
call with a Click event
- one
- double_click
- one
AceButton::check()
call with a DoubleClick event
- one
- long_press/repeat_press
- one
AceButton::check()
call with LongPress and RepeatPress events
- one
- ButtonConfigFast1 (AVR-only)
- 1 x
AceButton::check()
calls usingButtonConfigFast1<>
with no events
- 1 x
- ButtonConfigFast2 (AVR-only)
- 2 x
AceButton::check()
calls usingButtonConfigFast2<>
with no events
- 2 x
- ButtonConfigFast3 (AVR-only)
- 3 x
AceButton::check()
calls usingButtonConfigFast3<>
with no events
- 3 x
- Encoded4To2ButtonConfig
- 3 x
AceButton::check()
calls usingEncoded4To2ButtonConfig
with no events
- 3 x
- Encoded8To3ButtonConfig
- 7 x
AceButton::check()
calls usingEncoded8To3ButtonConfig
with no events
- 7 x
- EncodedButtonConfig
- one
EncodedButtonConfig::checkButtons()
call to support 7 virtual buttons, with no events
- one
- LadderButtonConfig
- one
LadderButtonConfig::checkButtons()
call to support 7 virtual buttons, with no events
- one
- 16MHz ATmega328P
- Arduino IDE 1.8.19, Arduino CLI 0.31.0
- Arduino AVR Boards 1.8.4
micros()
has a resolution of 4 microseconds
Sizes of Objects:
sizeof(AceButton): 17
sizeof(ButtonConfig): 20
sizeof(ButtonConfigFast1<>): 20
sizeof(ButtonConfigFast2<>): 20
sizeof(ButtonConfigFast3<>): 20
sizeof(Encoded4To2ButtonConfig): 23
sizeof(Encoded8To3ButtonConfig): 24
sizeof(EncodedButtonConfig): 27
sizeof(LadderButtonConfig): 28
CPU:
+---------------------------+-------------+---------+
| Button Event | min/avg/max | samples |
|---------------------------+-------------+---------|
| idle | 12/ 16/ 24 | 1929 |
| press/release | 12/ 17/ 28 | 1924 |
| click | 12/ 16/ 28 | 1925 |
| double_click | 12/ 16/ 32 | 1922 |
| long_press/repeat_press | 12/ 18/ 28 | 1923 |
|---------------------------+-------------+---------|
| ButtonConfigFast1 | 12/ 16/ 24 | 1932 |
| ButtonConfigFast2 | 20/ 30/ 40 | 1905 |
| ButtonConfigFast3 | 32/ 44/ 52 | 1880 |
|---------------------------+-------------+---------|
| Encoded4To2ButtonConfig | 60/ 73/ 80 | 1831 |
| Encoded8To3ButtonConfig | 168/196/204 | 1645 |
| EncodedButtonConfig | 84/110/116 | 1769 |
| LadderButtonConfig | 184/211/288 | 1625 |
+---------------------------+-------------+---------+
- 16 MHz ATmega32U4
- Arduino IDE 1.8.19, Arduino CLI 0.31.0
- SparkFun AVR Boards 1.1.13
micros()
has a resolution of 4 microseconds
Sizes of Objects:
sizeof(AceButton): 17
sizeof(ButtonConfig): 20
sizeof(ButtonConfigFast1<>): 20
sizeof(ButtonConfigFast2<>): 20
sizeof(ButtonConfigFast3<>): 20
sizeof(Encoded4To2ButtonConfig): 23
sizeof(Encoded8To3ButtonConfig): 24
sizeof(EncodedButtonConfig): 27
sizeof(LadderButtonConfig): 28
CPU:
+---------------------------+-------------+---------+
| Button Event | min/avg/max | samples |
|---------------------------+-------------+---------|
| idle | 12/ 16/ 24 | 1929 |
| press/release | 12/ 17/ 32 | 1924 |
| click | 12/ 16/ 28 | 1924 |
| double_click | 12/ 16/ 32 | 1921 |
| long_press/repeat_press | 12/ 18/ 28 | 1923 |
|---------------------------+-------------+---------|
| ButtonConfigFast1 | 12/ 16/ 24 | 1931 |
| ButtonConfigFast2 | 20/ 29/ 40 | 1904 |
| ButtonConfigFast3 | 32/ 44/ 56 | 1879 |
|---------------------------+-------------+---------|
| Encoded4To2ButtonConfig | 64/ 76/ 88 | 1825 |
| Encoded8To3ButtonConfig | 176/205/216 | 1632 |
| EncodedButtonConfig | 84/113/124 | 1767 |
| LadderButtonConfig | 180/208/276 | 1630 |
+---------------------------+-------------+---------+
- SAMD51, 120 MHz ARM Cortex-M4
- Arduino IDE 1.8.19, Arduino CLI 0.31.0
- Seeeduino SAMD 1.8.4
Sizes of Objects:
sizeof(AceButton): 20
sizeof(ButtonConfig): 24
sizeof(Encoded4To2ButtonConfig): 28
sizeof(Encoded8To3ButtonConfig): 28
sizeof(EncodedButtonConfig): 36
sizeof(LadderButtonConfig): 36
CPU:
+---------------------------+-------------+---------+
| Button Event | min/avg/max | samples |
|---------------------------+-------------+---------|
| idle | 5/ 8/ 16 | 1967 |
| press/release | 5/ 9/ 15 | 1965 |
| click | 5/ 9/ 15 | 1966 |
| double_click | 5/ 8/ 16 | 1965 |
| long_press/repeat_press | 5/ 9/ 16 | 1964 |
|---------------------------+-------------+---------|
| Encoded4To2ButtonConfig | 21/ 31/ 39 | 1924 |
| Encoded8To3ButtonConfig | 55/ 79/ 86 | 1840 |
| EncodedButtonConfig | 31/ 55/ 63 | 1880 |
| LadderButtonConfig | 42/ 64/ 79 | 1866 |
+---------------------------+-------------+---------+
- STM32 "Blue Pill", STM32F103C8, 72 MHz ARM Cortex-M3
- Arduino IDE 1.8.19, Arduino CLI 0.31.0
- STM32duino 2.5.0
Sizes of Objects:
sizeof(AceButton): 20
sizeof(ButtonConfig): 24
sizeof(Encoded4To2ButtonConfig): 28
sizeof(Encoded8To3ButtonConfig): 28
sizeof(EncodedButtonConfig): 36
sizeof(LadderButtonConfig): 36
CPU:
+---------------------------+-------------+---------+
| Button Event | min/avg/max | samples |
|---------------------------+-------------+---------|
| idle | 3/ 5/ 6 | 2002 |
| press/release | 3/ 6/ 8 | 2002 |
| click | 3/ 5/ 11 | 2002 |
| double_click | 3/ 5/ 10 | 2002 |
| long_press/repeat_press | 3/ 6/ 7 | 2002 |
|---------------------------+-------------+---------|
| Encoded4To2ButtonConfig | 16/ 22/ 23 | 2002 |
| Encoded8To3ButtonConfig | 46/ 59/ 60 | 2002 |
| EncodedButtonConfig | 24/ 38/ 42 | 2002 |
| LadderButtonConfig | 82/ 95/ 96 | 2002 |
+---------------------------+-------------+---------+
- SAMD51, 120 MHz ARM Cortex-M4
- Arduino IDE 1.8.19, Arduino CLI 0.31.0
- Adafruit SAMD 1.7.11
Sizes of Objects:
sizeof(AceButton): 20
sizeof(ButtonConfig): 24
sizeof(Encoded4To2ButtonConfig): 28
sizeof(Encoded8To3ButtonConfig): 28
sizeof(EncodedButtonConfig): 36
sizeof(LadderButtonConfig): 36
CPU:
+---------------------------+-------------+---------+
| Button Event | min/avg/max | samples |
|---------------------------+-------------+---------|
| idle | 1/ 2/ 4 | 1994 |
| press/release | 1/ 2/ 4 | 1994 |
| click | 1/ 2/ 4 | 1994 |
| double_click | 1/ 2/ 4 | 1994 |
| long_press/repeat_press | 1/ 2/ 4 | 1993 |
|---------------------------+-------------+---------|
| Encoded4To2ButtonConfig | 5/ 8/ 10 | 1982 |
| Encoded8To3ButtonConfig | 14/ 21/ 23 | 1956 |
| EncodedButtonConfig | 9/ 16/ 18 | 1967 |
| LadderButtonConfig | 33/ 41/ 43 | 1919 |
+---------------------------+-------------+---------+
- NodeMCU 1.0 clone, 80MHz ESP8266
- Arduino IDE 1.8.19, Arduino CLI 0.31.0
- ESP8266 Boards 3.0.2
Sizes of Objects:
sizeof(AceButton): 20
sizeof(ButtonConfig): 24
sizeof(Encoded4To2ButtonConfig): 28
sizeof(Encoded8To3ButtonConfig): 28
sizeof(EncodedButtonConfig): 36
sizeof(LadderButtonConfig): 36
CPU:
+---------------------------+-------------+---------+
| Button Event | min/avg/max | samples |
|---------------------------+-------------+---------|
| idle | 6/ 8/ 62 | 1920 |
| press/release | 6/ 8/ 45 | 1921 |
| click | 6/ 7/ 18 | 1921 |
| double_click | 6/ 7/ 12 | 1922 |
| long_press/repeat_press | 6/ 8/ 12 | 1920 |
|---------------------------+-------------+---------|
| Encoded4To2ButtonConfig | 22/ 27/ 46 | 1879 |
| Encoded8To3ButtonConfig | 56/ 67/ 76 | 1810 |
| EncodedButtonConfig | 43/ 54/ 70 | 1841 |
| LadderButtonConfig | 81/ 93/212 | 1772 |
+---------------------------+-------------+---------+
- ESP32-01 Dev Board, 240 MHz Tensilica LX6
- Arduino IDE 1.8.19, Arduino CLI 0.31.0
- ESP32 Boards 2.0.9
Sizes of Objects:
sizeof(AceButton): 20
sizeof(ButtonConfig): 24
sizeof(Encoded4To2ButtonConfig): 28
sizeof(Encoded8To3ButtonConfig): 28
sizeof(EncodedButtonConfig): 36
sizeof(LadderButtonConfig): 36
CPU:
+---------------------------+-------------+---------+
| Button Event | min/avg/max | samples |
|---------------------------+-------------+---------|
| idle | 2/ 3/ 18 | 2002 |
| press/release | 2/ 2/ 13 | 2002 |
| click | 2/ 2/ 8 | 2002 |
| double_click | 2/ 2/ 8 | 2002 |
| long_press/repeat_press | 2/ 2/ 8 | 2002 |
|---------------------------+-------------+---------|
| Encoded4To2ButtonConfig | 6/ 7/ 20 | 2002 |
| Encoded8To3ButtonConfig | 15/ 18/ 22 | 2002 |
| EncodedButtonConfig | 11/ 14/ 25 | 2002 |
| LadderButtonConfig | 103/107/251 | 2002 |
+---------------------------+-------------+---------+