Skip to content

RFC: Ways to enable allocation-free buffer operations #4244

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
peterhinch opened this issue Oct 16, 2018 · 3 comments
Open

RFC: Ways to enable allocation-free buffer operations #4244

peterhinch opened this issue Oct 16, 2018 · 3 comments
Labels
enhancement Feature requests, new feature implementations

Comments

@peterhinch
Copy link
Contributor

It is difficult to perform I2C reads of variable length data in an interrupt context. I tried pre-allocating a buffer, creating a memoryview, and issuing

i2c.readfrom_into(addr, mv[0 : num_bytes])  # mv is the memoryview instance

Alas mv[x:y] instantiates a new memoryview causing an allocation. Consequently with a preallocated buffer you are forced to fill the entire buffer if allocation is to be avoided. Depending on the remote hardware this may be impossible.

In practice you might want to read into a buffer which has already accumulated some data (eg a circular buffer). The length of data to be read may also change at runtime. An option would be for readfrom_into to take two additional parameters: offset and size. Reading would start at offset and end when size bytes were received or the buffer became full. Defaults (0 and -1) could be used to provide existing behaviour.

This seems rather widespread. Code which reads into, and writes from, preallocated buffers appears to offer the promise of allocation-free operation but falls at the last hurdle of actually delivering it.

Or is there any way to ensure memoryview objects don't have this side-effect? The following fails:

from pyb import Timer
a = bytearray(10)
m = memoryview(a)
b = bytearray((1,2))
def cb(_):
    m[3:5] = b  # bang
t = Timer(1, freq=1, callback=cb)
@pfalcon
Copy link
Contributor

pfalcon commented Oct 16, 2018

Surely #2552, #2180, #2622, #3382 talked about this and more years ago?

@SpotlightKid
Copy link
Contributor

All of these issues are still open.

@dpgeorge
Copy link
Member

Alas mv[x:y] instantiates a new memoryview causing an allocation.

It also allocates an intermediate slice object for x:y, along with the memoryview.

One way to handle this issue is to pre-create the memoryview objects, as is done here: https://github.com/micropython/micropython/blob/master/drivers/display/lcd160cr.py#L70-L71
But that's pretty ugly.

An option would be for readfrom_into to take two additional parameters: offset and size
...
This seems rather widespread. Code which reads into, and writes from, preallocated buffers appears to offer the promise of allocation-free operation but falls at the last hurdle of actually delivering it.

It might seem convenient to add offset/size, but that doesn't scale well because there are many read/write functions/methods which would need such addition. Instead I would prefer to find a way to make it so a memoryview doesn't need to take any heap memory, similar to parts of the discussion in #2552. That's then something which can be easily composed in general ways.

For example, with the proposal in #4020 to extend writeto to take multiple buffers like i2c.writeto(addr, [buf1, buf2]), that works much better by having an "inplace memoryview" and passing them in as i2c.writeto(addr, [mv1, mv2]), rather than trying to extend it to take offset/size likei2c.writeto(addr, [buf1, off1, size1, buf2, off2, size2]).

tannewt added a commit to tannewt/circuitpython that referenced this issue Feb 23, 2021
Added Unexpected Maker TinyS2 board definition
@jonnor jonnor added the enhancement Feature requests, new feature implementations label Sep 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Feature requests, new feature implementations
Projects
None yet
Development

No branches or pull requests

5 participants