aboutsummaryrefslogtreecommitdiffstats
path: root/docs/Benchmarks.md
blob: 976e7b7f95ea454f746972856112029b4c980c6c (plain)
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
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
This document describes Klipper benchmarks.

Micro-controller Benchmarks
===========================

This section describes the mechanism used to generate the Klipper
micro-controller step rate benchmarks.

The primary goal of the benchmarks is to provide a consistent
mechanism for measuring the impact of coding changes within the
software. A secondary goal is to provide high-level metrics for
comparing the performance between chips and between software
platforms.

The step rate benchmark is designed to find the maximum stepping rate
that the hardware and software can reach. This benchmark stepping rate
is not achievable in day-to-day use as Klipper needs to perform other
tasks (eg, mcu/host communication, temperature reading, endstop
checking) in any real-world usage.

In general, the pins for the benchmark tests are chosen to flash LEDs
or other innocuous pins. **Always verify that it is safe to drive the
configured pins prior to running a benchmark.** It is not recommended
to drive an actual stepper during a benchmark.

## Step rate benchmark test ##

The test is performed using the console.py tool (described in
[Debugging.md](Debugging.md)). The micro-controller is configured for
the particular hardware platform (see below) and then the following is
cut-and-paste into the console.py terminal window:
```
SET start_clock {clock+freq}
SET ticks 1000

reset_step_clock oid=0 clock={start_clock}
set_next_step_dir oid=0 dir=0
queue_step oid=0 interval={ticks} count=60000 add=0
set_next_step_dir oid=0 dir=1
queue_step oid=0 interval=3000 count=1 add=0

reset_step_clock oid=1 clock={start_clock}
set_next_step_dir oid=1 dir=0
queue_step oid=1 interval={ticks} count=60000 add=0
set_next_step_dir oid=1 dir=1
queue_step oid=1 interval=3000 count=1 add=0

reset_step_clock oid=2 clock={start_clock}
set_next_step_dir oid=2 dir=0
queue_step oid=2 interval={ticks} count=60000 add=0
set_next_step_dir oid=2 dir=1
queue_step oid=2 interval=3000 count=1 add=0
```

The above tests three steppers simultaneously stepping. If running the
above results in a "Rescheduled timer in the past" or "Stepper too far
in past" error then it indicates the `ticks` parameter is too low (it
results in a stepping rate that is too fast). The goal is to find the
lowest setting of the ticks parameter that reliably results in a
successful completion of the test. It should be possible to bisect the
ticks parameter until a stable value is found.

On a failure, one can copy-and-paste the following to clear the error
in preparation for the next test:
```
clear_shutdown
```

To obtain the single stepper and dual stepper benchmarks, the same
configuration sequence is used, but only the first block (for the
single stepper case) or first two blocks (for the dual stepper case)
of the above test is cut-and-paste into the console.py window.

To produce the benchmarks found in the Features.md document, the total
number of steps per second is calculated by multiplying the number of
active steppers with the nominal mcu frequency and dividing by the
final ticks parameter. The results are rounded to the nearest K. For
example, with three active steppers:
```
ECHO Test result is: {"%.0fK" % (3. * freq / ticks / 1000.)}
```

Benchmarks may be run with the micro-controller code compiled using a
"step pulse duration" of zero (the tables below report this as "no
delay"). This configuration is believed to be valid in real-world
usage when one is solely using Trinamic stepper drivers. The results
of these benchmarks are not reported in the Features.md document.

### AVR step rate benchmark ###

The following configuration sequence is used on AVR chips:
```
PINS arduino
allocate_oids count=3
config_stepper oid=0 step_pin=ar29 dir_pin=ar28 min_stop_interval=0 invert_step=0
config_stepper oid=1 step_pin=ar27 dir_pin=ar26 min_stop_interval=0 invert_step=0
config_stepper oid=2 step_pin=ar23 dir_pin=ar22 min_stop_interval=0 invert_step=0
finalize_config crc=0
```

The test was last run on commit `01d2183f` with gcc version `avr-gcc
(GCC) 5.4.0`. Both the 16Mhz and 20Mhz tests were run using simulavr
configured for an atmega644p (previous tests have confirmed simulavr
results match tests on both a 16Mhz at90usb and a 16Mhz atmega2560).

| avr              | ticks |
| ---------------- | ----- |
| 1 stepper        | 104   |
| 2 stepper        | 296   |
| 3 stepper        | 472   |

### Arduino Due step rate benchmark ###

The following configuration sequence is used on the Due:
```
allocate_oids count=3
config_stepper oid=0 step_pin=PB27 dir_pin=PA21 min_stop_interval=0 invert_step=0
config_stepper oid=1 step_pin=PB26 dir_pin=PC30 min_stop_interval=0 invert_step=0
config_stepper oid=2 step_pin=PA21 dir_pin=PC30 min_stop_interval=0 invert_step=0
finalize_config crc=0
```

The test was last run on commit `8d4a5c16` with gcc version
`arm-none-eabi-gcc (Fedora 7.4.0-1.fc30) 7.4.0`.

| sam3x8e              | ticks |
| -------------------- | ----- |
| 1 stepper            | 388   |
| 2 stepper            | 405   |
| 3 stepper            | 576   |
| 1 stepper (no delay) | 77    |
| 3 stepper (no delay) | 299   |

### Duet Maestro step rate benchmark ###

The following configuration sequence is used on the Duet Maestro:
```
allocate_oids count=3
config_stepper oid=0 step_pin=PC26 dir_pin=PC18 min_stop_interval=0 invert_step=0
config_stepper oid=1 step_pin=PC26 dir_pin=PA8 min_stop_interval=0 invert_step=0
config_stepper oid=2 step_pin=PC26 dir_pin=PB4 min_stop_interval=0 invert_step=0
finalize_config crc=0
```

The test was last run on commit `8d4a5c16` with gcc version
`arm-none-eabi-gcc (Fedora 7.4.0-1.fc30) 7.4.0`.

| sam4s8c              | ticks |
| -------------------- | ----- |
| 1 stepper            | 527   |
| 2 stepper            | 535   |
| 3 stepper            | 638   |
| 1 stepper (no delay) | 70    |
| 3 stepper (no delay) | 254   |

### Duet Wifi step rate benchmark ###

The following configuration sequence is used on the Duet Wifi:
```
allocate_oids count=4
config_stepper oid=0 step_pin=PD6 dir_pin=PD11 min_stop_interval=0 invert_step=0
config_stepper oid=1 step_pin=PD7 dir_pin=PD12 min_stop_interval=0 invert_step=0
config_stepper oid=2 step_pin=PD8 dir_pin=PD13 min_stop_interval=0 invert_step=0
config_stepper oid=3 step_pin=PD5 dir_pin=PA1 min_stop_interval=0 invert_step=0
finalize_config crc=0

```

The test was last run on commit `59a60d68` with gcc version
`arm-none-eabi-gcc 7.3.1 20180622 (release)
[ARM/embedded-7-branch revision 261907]`.

| sam4e8e          | ticks |
| ---------------- | ----- |
| 1 stepper        | 519   |
| 2 stepper        | 520   |
| 3 stepper        | 525   |
| 4 stepper        | 703   |

### Beaglebone PRU step rate benchmark ###

The following configuration sequence is used on the PRU:
```
PINS beaglebone
allocate_oids count=3
config_stepper oid=0 step_pin=P8_13 dir_pin=P8_12 min_stop_interval=0 invert_step=0
config_stepper oid=1 step_pin=P8_15 dir_pin=P8_14 min_stop_interval=0 invert_step=0
config_stepper oid=2 step_pin=P8_19 dir_pin=P8_18 min_stop_interval=0 invert_step=0
finalize_config crc=0
```

The test was last run on commit `b161a69e` with gcc version `pru-gcc
(GCC) 8.0.0 20170530 (experimental)`.

| pru              | ticks |
| ---------------- | ----- |
| 1 stepper        | 861   |
| 2 stepper        | 853   |
| 3 stepper        | 883   |

### STM32F042 step rate benchmark ###

The following configuration sequence is used on the STM32F042:
```
allocate_oids count=3
config_stepper oid=0 step_pin=PA1 dir_pin=PA2 min_stop_interval=0 invert_step=0
config_stepper oid=1 step_pin=PA3 dir_pin=PA2 min_stop_interval=0 invert_step=0
config_stepper oid=2 step_pin=PB8 dir_pin=PA2 min_stop_interval=0 invert_step=0
finalize_config crc=0
```

The test was last run on commit `0b0c47c5` with gcc version
`arm-none-eabi-gcc (Fedora 9.2.0-1.fc30) 9.2.0`.

| stm32f042        | ticks |
| ---------------- | ----- |
| 1 stepper        | 247   |
| 2 stepper        | 328   |
| 3 stepper        | 558   |

### STM32F103 step rate benchmark ###

The following configuration sequence is used on the STM32F103:
```
allocate_oids count=3
config_stepper oid=0 step_pin=PC13 dir_pin=PB5 min_stop_interval=0 invert_step=0
config_stepper oid=1 step_pin=PB3 dir_pin=PB6 min_stop_interval=0 invert_step=0
config_stepper oid=2 step_pin=PA4 dir_pin=PB7 min_stop_interval=0 invert_step=0
finalize_config crc=0
```

The test was last run on commit `8d4a5c16` with gcc version
`arm-none-eabi-gcc (Fedora 7.4.0-1.fc30) 7.4.0`.

| stm32f103            | ticks |
| -------------------- | ----- |
| 1 stepper            | 347   |
| 2 stepper            | 372   |
| 3 stepper            | 600   |
| 1 stepper (no delay) | 71    |
| 3 stepper (no delay) | 288   |

### STM32F4 step rate benchmark ###

The following configuration sequence is used on the STM32F4:
```
allocate_oids count=4
config_stepper oid=0 step_pin=PA5 dir_pin=PB5 min_stop_interval=0 invert_step=0
config_stepper oid=1 step_pin=PB2 dir_pin=PB6 min_stop_interval=0 invert_step=0
config_stepper oid=2 step_pin=PB3 dir_pin=PB7 min_stop_interval=0 invert_step=0
config_stepper oid=3 step_pin=PB3 dir_pin=PB8 min_stop_interval=0 invert_step=0
finalize_config crc=0
```

The test was last run on commit `8d4a5c16` with gcc version
`arm-none-eabi-gcc (Fedora 7.4.0-1.fc30) 7.4.0`. The STM32F407 results
were obtained by running an STM32F407 binary on an STM32F446 (and thus
using a 168Mhz clock).

| stm32f446            | ticks |
| -------------------- | ----- |
| 1 stepper            | 757   |
| 2 stepper            | 761   |
| 3 stepper            | 757   |
| 4 stepper            | 767   |
| 1 stepper (no delay) | 51    |
| 3 stepper (no delay) | 226   |

| stm32f407            | ticks |
| -------------------- | ----- |
| 1 stepper            | 709   |
| 2 stepper            | 714   |
| 3 stepper            | 709   |
| 4 stepper            | 729   |
| 1 stepper (no delay) | 52    |
| 3 stepper (no delay) | 226   |

### LPC176x step rate benchmark ###

The following configuration sequence is used on the LPC176x:
```
allocate_oids count=3
config_stepper oid=0 step_pin=P1.20 dir_pin=P1.18 min_stop_interval=0 invert_step=0
config_stepper oid=1 step_pin=P1.21 dir_pin=P1.18 min_stop_interval=0 invert_step=0
config_stepper oid=2 step_pin=P1.23 dir_pin=P1.18 min_stop_interval=0 invert_step=0
finalize_config crc=0
```

The test was last run on commit `8d4a5c16` with gcc version
`arm-none-eabi-gcc (Fedora 7.4.0-1.fc30) 7.4.0`. The 120Mhz LPC1769
results were obtained by overclocking an LPC1768 to 120Mhz.

| lpc1768              | ticks |
| -------------------- | ----- |
| 1 stepper            | 448   |
| 2 stepper            | 450   |
| 3 stepper            | 523   |
| 1 stepper (no delay) | 56    |
| 3 stepper (no delay) | 240   |

| lpc1769              | ticks |
| -------------------- | ----- |
| 1 stepper            | 525   |
| 2 stepper            | 526   |
| 3 stepper            | 545   |
| 1 stepper (no delay) | 56    |
| 3 stepper (no delay) | 240   |

### SAMD21 step rate benchmark ###

The following configuration sequence is used on the SAMD21:
```
allocate_oids count=3
config_stepper oid=0 step_pin=PA27 dir_pin=PA20 min_stop_interval=0 invert_step=0
config_stepper oid=1 step_pin=PB3 dir_pin=PA21 min_stop_interval=0 invert_step=0
config_stepper oid=2 step_pin=PA17 dir_pin=PA21 min_stop_interval=0 invert_step=0
finalize_config crc=0
```

The test was last run on commit `8d4a5c16` with gcc version
`arm-none-eabi-gcc (Fedora 7.4.0-1.fc30) 7.4.0` on a SAMD21G18
micro-controller.

| samd21               | ticks |
| -------------------- | ----- |
| 1 stepper            | 277   |
| 2 stepper            | 410   |
| 3 stepper            | 664   |
| 1 stepper (no delay) | 83    |
| 3 stepper (no delay) | 321   |

### SAMD51 step rate benchmark ###

The following configuration sequence is used on the SAMD51:
```
allocate_oids count=5
config_stepper oid=0 step_pin=PA22 dir_pin=PA20 min_stop_interval=0 invert_step=0
config_stepper oid=1 step_pin=PA22 dir_pin=PA21 min_stop_interval=0 invert_step=0
config_stepper oid=2 step_pin=PA22 dir_pin=PA19 min_stop_interval=0 invert_step=0
config_stepper oid=3 step_pin=PA22 dir_pin=PA18 min_stop_interval=0 invert_step=0
config_stepper oid=4 step_pin=PA23 dir_pin=PA17 min_stop_interval=0 invert_step=0
finalize_config crc=0
```

The test was last run on commit `524ebbc7` with gcc version
`arm-none-eabi-gcc (Fedora 9.2.0-1.fc30) 9.2.0` on a SAMD51J19A
micro-controller.

| samd51               | ticks |
| -------------------- | ----- |
| 1 stepper            | 516   |
| 2 stepper            | 520   |
| 3 stepper            | 520   |
| 4 stepper            | 631   |
| 1 stepper (200Mhz)   | 839   |
| 2 stepper (200Mhz)   | 838   |
| 3 stepper (200Mhz)   | 838   |
| 4 stepper (200Mhz)   | 838   |
| 5 stepper (200Mhz)   | 891   |
| 1 stepper (no delay) | 42    |
| 3 stepper (no delay) | 194   |

### Linux MCU step rate benchmark ###

The following configuration sequence is used on a Raspberry Pi:
```
allocate_oids count=3
config_stepper oid=0 step_pin=gpio2 dir_pin=gpio3 min_stop_interval=0 invert_step=0
config_stepper oid=1 step_pin=gpio4 dir_pin=gpio5 min_stop_interval=0 invert_step=0
config_stepper oid=2 step_pin=gpio6 dir_pin=gpio7 min_stop_interval=0 invert_step=0
finalize_config crc=0
```

The test was last run on commit `06437c58` with gcc version `gcc
(Raspbian 6.3.0-18+rpi1+deb9u1) 6.3.0 20170516` on a Raspberry Pi 3
(revision a22082).

| Linux (RPi3)         | ticks |
| -------------------- | ----- |
| 1 stepper            | 340   |
| 2 stepper            | 356   |
| 3 stepper            | 450   |

## Command dispatch benchmark ##

The command dispatch benchmark tests how many "dummy" commands the
micro-controller can process. It is primarily a test of the hardware
communication mechanism. The test is run using the console.py tool
(described in [Debugging.md](Debugging.md)). The following is
cut-and-paste into the console.py terminal window:
```
DELAY {clock + 2*freq} get_uptime
FLOOD 100000 0.0 end_group
get_uptime
```

When the test completes, determine the difference between the clocks
reported in the two "uptime" response messages. The total number of
commands per second is then `100000 * mcu_frequency / clock_diff`.

Note that this test may saturate the USB/CPU capacity of a Raspberry
Pi. The benchmarks below are with console.py running on a desktop
class machine with the device connected via a high-speed hub.

| MCU                 | Rate | Build    | Build compiler      |
| ------------------- | ---- | -------- | ------------------- |
| pru (shared memory) |   5K | b161a69e | pru-gcc (GCC) 8.0.0 20170530 (experimental) |
| stm32f042 (CAN)     |  18K | c105adc8 | arm-none-eabi-gcc (GNU Tools 7-2018-q3-update) 7.3.1 |
| atmega2560 (serial) |  23K | b161a69e | avr-gcc (GCC) 4.8.1 |
| sam3x8e (serial)    |  23K | b161a69e | arm-none-eabi-gcc (Fedora 7.1.0-5.fc27) 7.1.0 |
| at90usb1286 (USB)   |  75K | 01d2183f | avr-gcc (GCC) 5.4.0 |
| samd21 (USB)        | 223K | 01d2183f | arm-none-eabi-gcc (Fedora 7.4.0-1.fc30) 7.4.0 |
| stm32f103 (USB)     | 355K | 01d2183f | arm-none-eabi-gcc (Fedora 7.4.0-1.fc30) 7.4.0 |
| sam3x8e (USB)       | 418K | 01d2183f | arm-none-eabi-gcc (Fedora 7.4.0-1.fc30) 7.4.0 |
| lpc1768 (USB)       | 534K | 01d2183f | arm-none-eabi-gcc (Fedora 7.4.0-1.fc30) 7.4.0 |
| lpc1769 (USB)       | 628K | 01d2183f | arm-none-eabi-gcc (Fedora 7.4.0-1.fc30) 7.4.0 |
| sam4s8c (USB)       | 650K | 8d4a5c16 | arm-none-eabi-gcc (Fedora 7.4.0-1.fc30) 7.4.0 |
| samd51 (USB)        | 864K | 01d2183f | arm-none-eabi-gcc (Fedora 7.4.0-1.fc30) 7.4.0 |
| stm32f446 (USB)     | 870K | 01d2183f | arm-none-eabi-gcc (Fedora 7.4.0-1.fc30) 7.4.0 |

Host Benchmarks
===============

It is possible to run timing tests on the host software using the
"batch mode" processing mechanism (described in
[Debugging.md](Debugging.md)). This is typically done by choosing a
large and complex G-Code file and timing how long it takes for the
host software to process it. For example:
```
time ~/klippy-env/bin/python ./klippy/klippy.py config/example.cfg -i something_complex.gcode -o /dev/null -d out/klipper.dict
```