docs/reference: Add strings vs bytes to speed optimisation tips.

Also add some additional context links, suggestions for alternative
classes, etc.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
This commit is contained in:
Angus Gratton
2025-02-04 12:20:38 +11:00
committed by Damien George
parent bab099826e
commit 0a55f1f40c
3 changed files with 40 additions and 1 deletions

View File

@@ -19,6 +19,10 @@ Classes
array are given by *iterable*. If it is not provided, an empty
array is created.
In addition to the methods below, array objects also implement the buffer
protocol. This means the contents of the entire array can be accessed as raw
bytes via a `memoryview` or other interfaces which use this protocol.
.. method:: append(val)
Append new element *val* to the end of array, growing it.

View File

@@ -19,6 +19,8 @@ Functions and types
.. class:: bytearray()
|see_cpython| `python:bytearray`.
.. class:: bytes()
|see_cpython| `python:bytes`.
@@ -104,6 +106,8 @@ Functions and types
.. class:: memoryview()
|see_cpython| `python:memoryview`.
.. function:: min()
.. function:: next()

View File

@@ -57,6 +57,8 @@ and used in various methods.
This is covered in further detail :ref:`Controlling garbage collection <controlling_gc>` below.
.. _speed_buffers:
Buffers
~~~~~~~
@@ -69,6 +71,13 @@ example, objects which support stream interface (e.g., file or UART) provide ``r
method which allocates new buffer for read data, but also a ``readinto()`` method
to read data into an existing buffer.
Some useful classes for creating reusable buffer objects:
- :class:`bytearray`
- :mod:`array` (:ref:`discussed below<speed_arrays>`)
- :class:`io.StringIO` and :class:`io.BytesIO`
- :class:`micropython.RingIO`
Floating point
~~~~~~~~~~~~~~
@@ -80,15 +89,20 @@ point to sections of the code where performance is not paramount. For example,
capture ADC readings as integers values to an array in one quick go, and only then
convert them to floating-point numbers for signal processing.
.. _speed_arrays:
Arrays
~~~~~~
Consider the use of the various types of array classes as an alternative to lists.
The `array` module supports various element types with 8-bit elements supported
The :mod:`array` module supports various element types with 8-bit elements supported
by Python's built in `bytes` and `bytearray` classes. These data structures all store
elements in contiguous memory locations. Once again to avoid memory allocation in critical
code these should be pre-allocated and passed as arguments or as bound objects.
Memoryviews
~~~~~~~~~~~
When passing slices of objects such as `bytearray` instances, Python creates
a copy which involves allocation of the size proportional to the size of slice.
This can be alleviated using a `memoryview` object. The `memoryview` itself
@@ -118,6 +132,23 @@ of buffer and fills in entire buffer. What if you need to put data in the
middle of existing buffer? Just create a memoryview into the needed section
of buffer and pass it to ``readinto()``.
Strings vs Bytes
~~~~~~~~~~~~~~~~
MicroPython uses :ref:`string interning <qstr>` to save space when there are
multiple identical strings. Each time a new string is allocated at runtime (for
example, when two other strings are concatenated), MicroPython checks whether
the new string can be interned to save RAM.
If you have code which performs performance-critical string operations then
consider using :class:`bytes` objects and literals (i.e. ``b"abc"``). This skips
the interning check, and can be several times faster than performing the same
operations with string objects.
.. note:: The fastest performance will always be achieved by avoiding new object
creation entirely, for example with a reusable :ref:`buffer as described
above<speed_buffers>`.
Identifying the slowest section of code
---------------------------------------