-
Notifications
You must be signed in to change notification settings - Fork 18
Description
I won't pretend I have any idea how the mruby VM works, but I got curious about how well it runs on the ESP32, and did some black-box testing.
Board: DOIT ESP32 Devkit V1
Clock: 240 MHz
Testing: Oscilloscope, double checked with time after loop - time before loop
calculation.
Notes: mruby task pinned to Core 1, Core 1 watchdog timer disabled, so it doesn't crash.
Test 1: Class Methods
First up is a minimal project using the following code:
- mruby: mruby-esp32/mruby@9e64ec7
- system: mruby-esp32/mruby-esp32-system@5f2beff
- gpio: mruby-esp32/mruby-esp32-gpio@0842bda
mruby-print
,mruby-compiler
,mruby-io
from standard gems
Results
# Setup for all loops
led = ESP32::GPIO_NUM_2
ESP32::GPIO::pinMode(led, ESP32::GPIO_MODE_OUTPUT)
# 53 kHz
loop {
ESP32::GPIO::digital_write(2, 1)
ESP32::GPIO::digital_write(2, 0)
}
# 42 kHz
loop {
ESP32::GPIO::digital_write(led, ESP32::HIGH)
ESP32::GPIO::digital_write(led, ESP32::LOW)
}
# 35 kHz
loop {
ESP32::GPIO::digital_write(ESP32::GPIO_NUM_2, ESP32::HIGH)
ESP32::GPIO::digital_write(ESP32::GPIO_NUM_2, ESP32::LOW)
}
Test 2: Instance Methods
Next up is the esp32-2mb
folder from my project. This includes many more gems, but uses the exact C source from mruby-system
and mruby-gpio
, and I'm using the same mruby
.
The one big difference is, instead of ESP32::GPIO::digital_write
, I mapped the C function to an instance method, Board#digital_write
. $board
is an automatically created global instance.
Results
# Setup
include Denko
led = DigitalIO::Output.new(pin: 2)
# 67 kHz
# Literal values are fastest.
# Instance methods appear faster than Class/Module methods.
loop do
$board.digital_write(2, 1)
$board.digital_write(2, 0)
end
# 66 kHz
# Still fast with a local variable.
pin = 2
loop do
$board.digital_write(pin, 1)
$board.digital_write(pin, 0)
end
# 50 kHz
# led.pin is a getter for led@pin instance var.
loop do
$board.digital_write(led.pin, 1)
$board.digital_write(led.pin, 0)
end
# 40 kHz
# #digital_write also saves given value to led@state. Extra overhead.
loop do
led.digital_write(1)
led.digital_write(0)
end
# 32 kHz
# #on and #off just do the two lines in the above example.
loop do
led.on
led.off
end
# 32 kHz
# Aliases #on and #off. Aliasing looks like it's free.
loop do
led.high
led.low
end
# 18 kHz
# This LOOKS like it should be faster. It's not passing through led, not setting @state.
# But reading HIGH and LOW from Board are enough to make it slow.
# There are a lot of constants defined in Board. Maybe more makes it slower?
loop do
$board.digital_write(2, Board::HIGH)
$board.digital_write(2, Board::LOW)
end
# 16.5 kHz
# Even worse using reader method for pin number.
loop do
$board.digital_write(led.pin, Board::HIGH)
$board.digital_write(led.pin, Board::LOW)
end
# 16 kHz
# Worse again using reader methods for HIGH and LOW.
loop do
$board.digital_write(led.pin, $board.high)
$board.digital_write(led.pin, $board.low)
end
Observations
In decreasing order of speed for getting a value:
- Literal value
- Local variable with literal value
- Instance method that just returns a literal value from instance var
- Constant defined in Class
- Instance method that gets constant from its Class
It also looks like instance methods are a bit faster than Class/Module methods, comparing first example in each test.