Allocation when slicing memoryview instance

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Allocation when slicing memoryview instance

Post by pythoncoder » Tue Oct 16, 2018 12:12 pm

Am I suffering from brain-fade or is something wrong here? Tests done on a Pyboard using the onboard accelerometer as an I2C data source.

This sample works:

Code: Select all

from machine import I2C
from pyb import Timer
a = bytearray(2)
m = memoryview(a)
i = I2C(2)
def cb(_):
    i.readfrom_into(60, m)
t = Timer(1, freq=1, callback=cb)
but this produces a memory error:

Code: Select all

from machine import I2C
from pyb import Timer
a = bytearray(10)
m = memoryview(a)
i = I2C(2)
def cb(_):
    i.readfrom_into(60, m[0:2])
t = Timer(1, freq=1, callback=cb)
The callback works in that if I issue cb(0) at the REPL: the first two bytes of the 10 byte array are updated. A memoryview lets you take a slice into the original data without copying. So why is memory allocated?
Peter Hinch
Index to my micropython libraries.

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: machine.I2C: allocation reading into pre-allocated buffer

Post by Roberthh » Tue Oct 16, 2018 12:29 pm

I am also confused by the follwing, which I stumbled over a few days (or weeks) ago, and which did not meet my expectation:

Code: Select all

>>> s="1234567890"
>>> m=memoryview(s)
>>> m[0:2]
<memoryview>
>>> m[0]
49
>>> x=m[0:2]
>>> x
<memoryview>
>>> s[0:2]
'12'
>>> for _ in m[0:2]:
...     _
...
49
50
I expeceted m[0:2] to return the same as s[0:2]. Iterating through m it is however possible, but not slicing.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: machine.I2C: allocation reading into pre-allocated buffer

Post by pythoncoder » Tue Oct 16, 2018 12:50 pm

A slice of a memoryview returns another memoryview. A memoryview instance doesn't have the methods of the object it's based on, so there aren't many things you can do with it. Thus

Code: Select all

>>> a = b'the quick brown fox'
>>> a.find(b'q')
4
>>> m = memoryview(a)
>>> m.find(b'q')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'memoryview' object has no attribute 'find'
>>> 
You can cast it to the original type, but then you're creating a copy which normally defeats the object.

Code: Select all

a = bytearray(20)
m = memoryview(a)
m1 = m[1:3]  # m1 is another memoryview instance. Still points into the original bytearray.
b = bytearray(m1)  # b has the attributes of a bytearray. But it's a new instance.
This is true for CPython and MicroPython.
Peter Hinch
Index to my micropython libraries.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

This fails too. OK, I've got it.

Post by pythoncoder » Tue Oct 16, 2018 1:05 pm

Code: Select all

from machine import I2C
from pyb import Timer
a = bytearray(10)
m = memoryview(a)
b = bytearray((1,2))
def cb(_):
    m[3:5] = b
t = Timer(1, freq=1, callback=cb)
So the problem has nothing to do with I2C but with memoryview slicing.
[EDIT]
I've answered my own question: m[x:y] creates a new memoryview object on the heap. This implies it's impossible (in an interrupt context) to use I2C.readfrom_into to populate a circular buffer.

In any event I've come up with a better solution for my application.
Peter Hinch
Index to my micropython libraries.

jickster
Posts: 629
Joined: Thu Sep 07, 2017 8:57 pm

Re: Allocation when slicing memoryview instance

Post by jickster » Tue Oct 16, 2018 4:13 pm

Until scoped allocation is implemented.


Sent from my iPhone using Tapatalk Pro

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Allocation when slicing memoryview instance

Post by pythoncoder » Tue Oct 16, 2018 5:45 pm

Indeed. It does seem unfortunate that memoryview objects in particular use the heap. I have raised this RFC with a minimal test case. I'll be interested to see the response.
Peter Hinch
Index to my micropython libraries.

Post Reply