Python is the language that I write most of my code in and cPython is the interpreter that I use.
That’s quite typical:
python is cPython 99% of the time.
But what is that small fraction of other python interpreters?
Today I am featuring micropython: an independent project that fits python language into tiny (few kB or MB) bare metal platforms.
Billions of small devices around us have only few Kb of memory. The project demonstrates that few Kb is still enough to run python interpreter: it is not just a proof of a concept but rather do-your-usual-microcontroller-stuff-in-python concept.
Despite being micro, micropython delivers most of modern python experience.
There are some parts of the language that are not implemented (or rather shortcut).
At the same time, micropython features unique extensions that you do not find elsewhere!
This post is about the
micropython.viper decorator enabling maximal speed for integer buffer manipulations.
Python interpreters are known for being slow, sometimes too slow.
In cPython you can use various tools and “native” interfaces to
speed up performance-critical parts.
Same, in principle, applies to micropython.
Your best guess is to write performance-critical code in C and to
link it into firmware.
But there is also a tiny built-in compiler which you use towards
machine-fast code called Viper.
To enable it, you only need to put
@viper decorator on top of the target
For example, this is what I have in my pywatchos.
@micropython.viper def min_max(fr: int, val: int, to: int) -> int: if val < fr: return fr if val > to: return to return val
The above code will be translated into few machine instructions rather than python opcodes making it blazing fast. A cython analogue would look as following.
def min_max(int fr, int val, int to): if val < fr: return fr if val > to: return to return val
Cython does undergo multiple parsing, translations and linking stages.
@viper does not have most of it (which also means that you can barely implement complex logic).
But memory buffer operations is where viper can shine.
For example, the following function swaps even and odd bytes.
@micropython.viper def swap16(dst: ptr8, src: ptr8, size: int): for i in range(0, size, 2): tmp = src[i] dst[i] = src[i + 1] dst[i + 1] = tmp
I use it to convert between the big-endian BMP image file format and the little-endian ESP32
swap16 is more than 10 times faster than the corresponding pure-python analogue which will perform type checks multiple times per line.