-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathgenerate_readme.py
executable file
·282 lines (239 loc) · 10.4 KB
/
generate_readme.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
#!/usr/bin/python3
#
# Python script that regenerates the README.md from the embedded template. Uses
# ./generate_table.awk to regenerate the ASCII tables from the various *.txt
# files.
from subprocess import check_output
attiny_results = check_output(
"./generate_table.awk < attiny.txt", shell=True, text=True)
nano_results = check_output(
"./generate_table.awk < nano.txt", shell=True, text=True)
micro_results = check_output(
"./generate_table.awk < micro.txt", shell=True, text=True)
stm32_results = check_output(
"./generate_table.awk < stm32.txt", shell=True, text=True)
esp8266_results = check_output(
"./generate_table.awk < esp8266.txt", shell=True, text=True)
esp32_results = check_output(
"./generate_table.awk < esp32.txt", shell=True, text=True)
teensy32_results = check_output(
"./generate_table.awk < teensy32.txt", shell=True, text=True)
print(f"""\
# Memory Benchmark
The `MemoryBenchmark.ino` program compiles example code snippets using the
AceRoutine library. The `FEATURE` macro flag controls which feature is compiled.
The `collect.sh` edits this `FEATURE` flag programmatically, then runs the
Arduino IDE compiler on the program, and extracts the flash and static memory
usage into a text file (e.g. `nano.txt`).
The numbers shown below should be considered to be rough estimates. It is often
difficult to separate out the code size of the library from the overhead imposed
by the runtime environment of the processor. For example, it often seems like
the ESP8266 allocates flash memory in blocks of a certain quantity, so the
calculated flash size can jump around in unexpected ways.
**DO NOT EDIT**: This file was auto-generated using `make README.md`.
**Version**: AceRoutine v1.5.1
**Changes**:
* v1.1 to v1.2 saw a significant *decrease* of flash usage by about 200-400
bytes for various scenarios. This was due to several factors including:
* `Coroutine::setupCoroutine()` no longer sorts the coroutines in the linked
list by name
* `Coroutine::suspend()` and `resume()` no longer modify the linked list
* `CoroutineScheduler::runCoroutine()` simplified due to immutable
linked list
* `CoroutineScheduler::setupScheduler()` simplified due to immutable linked
list
* v1.3
* Remove virtual destructor on `Coroutine` class. Reduces flash memory
consumption by 500-600 bytes on AVR processors, 350 bytes on SAMD21, and
50-150 bytes on other 32-bit processors. The static memory is also reduced
by 14 bytes on AVR processors.
* Replace clock ticking virtual methods (`coroutineMicros()`,
`coroutineMillis()`, and `coroutineSeconds()`) with static functions that
delegate to `ClockInterface` which is a template parameter. Saves only
0-40 bytes of flash on on AVR processors, but 100-1500 bytes of flash on
32-bit processors.
* Add benchmark for 'One Delay Function' and 'Two Delay Functions` which use
functions with a non-blocking if-statement to implement the functionality
of a `COROUTINE()` that loops every 10 milliseconds.
* Remove `COROUTINE_DELAY_SECONDS()` functionality. Saves about 200 bytes on
AVR processors, mostly from the removal of `udiv1000()` which takes almost
180 bytes. Replacing with native `/1000` does not help much because native
long division consumes about 130 bytes and is 3X slower on AVR processors.
* Remove `COROUTINE_DELAY_MICRO()` functionality. Saves about 15-20 bytes
of flash memory per coroutine on AVR. Saves 80-100 bytes plus 20-30 bytes
of flash per coroutine on 32-bit processors.
* Add `Blink Function` and `Blink Coroutine`, 2 implementations of the same
asymmetric blink functionality where the HIGH level lasts for a different
duration than the LOW level.
* Remove `Coroutine::getName()`, `Coroutine::mName()`, and
`Coroutine::setupCoroutine()`. The human-readable name is no longer
retained. Saves 10-30 bytes of flash and 3 bytes of static memory per
coroutine instance for AVR; 10-40 bytes and 8 bytes of static memory per
instance on 32-bit processors.
* Use 2 different `Coroutine` subclasses, instead of 2 instances of the same
`Coroutine` subclass, for the "Scheduler, Two Coroutines" benchmark . This
makes it more functionally equal to the "Two Coroutines" benchmark which
automatically creates 2 different subclasses through the `COROUTINE()`
macro. Increases flash memory by 80-130 bytes across the board.
* v1.3.1
* Bring back `COROUTINE_DELAY_MICROS()` and `COROUTINE_DELAY_SECONDS()`
using an implementation that increases flash and static memory *only* if
they are used.
* `COROUTINE_DELAY_MICROS()` actually consumes about 30 bytes fewer
flash memory (on AVR) than `COROUTINE_DELAY()`, probably because there
is additional overhead in the Arduino `millis()` function compared to
`micros()`.
* `COROUTINE_DELAY_SECONDS()` consumes about 100 bytes more flash memory
(on AVR) compared to `COROUTINE_DELAY()` because of the division by
1000 which must be done in software on 8-bit processors.
* The `CoroutineScheduler` is forced to become simpler which reduces
flash usage by 10-20 bytes.
* v1.4
* Upgrade STM32duino Core to 2.0.0.
* Flash usage increases by 2.3kB across the board, but static RAM goes
down by 250 bytes.
* Very little change to AceRoutine code itself.
* "Blink Function" and "Blink Coroutine" both increase flash usage by
about 50 bytes, probably due to additional resource consumption of
`digitalWrite()` in 2.0.0.
* Upgrade SparkFun SAMD Core to 1.8.3.
* No change in memory usage.
* Add a dummy `FooClass` with virtual methods for Teensy 3.2 so that
`FEATURE_BASELINE` becomes a useful comparison to the other benchmarks.
Teensyduino seems to pull in `malloc()` and `free()` functions as soon as
any class with virtual methods are uses, unlike AVR where they are pulled
in only if the destructor is virtual.
* Add benchmarks for calling `CoroutineScheduler::setupCoroutine()`.
Increases flash memory by 50-60 bytes *per coroutine* (AVR) and 30-40
bytes per coroutine (32-bit processors).
* v1.4.1
* Upgrade tool chain
* Arduino IDE from 1.8.13 to 1.8.19
* Arduino CLI from 0.14.0 to 0.19.2
* Arduino AVR Core from 1.8.3 to 1.8.4
* STM32duino from 2.0.0 to 2.2.0
* ESP8266 Core from 2.7.4 to 3.0.2
* ESP32 Core from 1.0.6 to 2.0.2
* Teensyduino from 1.54 to 1.56
* v1.5
* Add support for human-readable names to coroutine.
* Increases flash usage by 6-10 bytes per coroutine, even if name isn't
used.
* Increases static ram by 3 bytes (AVR) and 4 bytes (32-bits) per
coroutine.
* Support `CoroutineProfiler` in the `CoroutineScheduler`.
* Increases the flash size of the `CoroutineScheduler` by 90-140 bytes
for both 8-bit and 32-bit processors, even if `CoroutineProfiler` is
not used. This is a one-time hit.
* Add `LogBinProfiler`
* Adds about 90 bytes of flash and 70 bytes of RAM on AVR.
* Adds about 140 bytes of flash and 70 bytes of RAM on ESP8266.
* Add `LogBinTableRenderer`
* Adds about 1400 bytes of flash and ~20 bytes of RAM on AVR.
* Adds about 1900 bytes of flash and ~0 bytes of RAM on ESP8266.
* Add `LogBinJsonRenderer`
* Adds about 900 bytes of flash and ~20 bytes of RAM on AVR.
* Adds about 1300 bytes of flash and ~0 bytes of RAM on ESP8266.
* v1.5.1
* Upgrade tool chain
* Arduino CLI from 0.19.2 to 0.27.1
* Arduino AVR Core from 1.8.4 to 1.8.5
* STM32duino from 2.2.0 to 2.3.0
* ESP32 Core from 2.0.2 to 2.0.5
* Teensyduino from 1.56 to 1.57
## How to Generate
This requires the [AUniter](https://github.com/bxparks/AUniter) script
to execute the Arduino IDE programmatically.
The `Makefile` has rules for several microcontrollers:
```
$ make benchmarks
```
produces the following files:
```
attiny.txt
nano.txt
micro.txt
stm32.txt
esp8266.txt
esp32.txt
teensy32.txt
```
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
```
## Results
* Baseline: A program that does (almost) nothing
* One Delay Function: A single non-blocking delay function that waits 10 millis.
* Two Delay Functions: Two non-blocking delay functions.
* One Coroutine: One instance of `Coroutine` that waits 10 millis, executed
directly through `runCoroutine()`.
* Two Coroutines: Two instances of `Coroutine` that wait 10 millis, executed
directly through `runCoroutine()`.
* Scheduler, One Coroutine: One instance of `Coroutine` executed through the
`CoroutineScheduler`.
* Scheduler, Two Coroutines: Two instances of `Coroutine` executed through the
`CoroutineScheduler`.
* Blink Function: A function that blinks the LED asymmetrically, with HIGH
lasting a different duration than LOW.
* Blink Coroutine: A `Coroutine` that blinks asymmetrically, exactly the same as
the `blink()` function.
### ATtiny85
* 8MHz ATtiny85
* Arduino IDE 1.8.19, Arduino CLI 0.27.1
* SpenceKonde/ATTinyCore 1.5.2
```
{attiny_results}
```
### Arduino Nano
* 16MHz ATmega328P
* Arduino IDE 1.8.19, Arduino CLI 0.27.1
* Arduino AVR Boards 1.8.5
```
{nano_results}
```
### SparkFun Pro Micro
* 16 MHz ATmega32U4
* Arduino IDE 1.8.19, Arduino CLI 0.27.1
* SparkFun AVR Boards 1.1.13
```
{micro_results}
```
### STM32 Blue Pill
* STM32F103C8, 72 MHz ARM Cortex-M3
* Arduino IDE 1.8.19, Arduino CLI 0.27.1
* STM32duino 2.3.0
```
{stm32_results}
```
### ESP8266
* NodeMCU 1.0 clone, 80MHz ESP8266
* Arduino IDE 1.8.19, Arduino CLI 0.27.1
* ESP8266 Boards 3.0.2
```
{esp8266_results}
```
### ESP32
* ESP32-01 Dev Board, 240 MHz Tensilica LX6
* Arduino IDE 1.8.19, Arduino CLI 0.27.1
* ESP32 Boards 2.0.5
```
{esp32_results}
```
### Teensy 3.2
* 96 MHz ARM Cortex-M4
* Arduino IDE 1.8.19, Arduino CLI 0.27.1
* Teensyduino 1.57
* Compiler options: "Faster"
```
{teensy32_results}
```
""")