-
-
Notifications
You must be signed in to change notification settings - Fork 863
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
Add PyProxyBufferMethods #1215
Add PyProxyBufferMethods #1215
Conversation
Great work! The ability to construct common JS ndarray of python's raw Buffer without copying data is enough for most of my cases. Although a question is: how to release such a variable and the proxy itself in JS? Should I simply set it to null or call some method like |
And also I suffered from some potential memory leaks, e.g.:
While in JS resize_img(img_bytes, ...), img_bytes is a Ref to the python bytes memory. So should I release the memory in JS by setting img_bytes=null ? If so , what's the necessarity of |
@daoxian You have to
Currently you need to say Note that pyodide is currently rather full of memory leaks, you have to take special care to avoid them.
Note that no matter what |
Here's an example: function resize_img(src_data, dst_data) {
let src_buffer = src_data.getRawBuffer();
let dst_buffer = dst_data.getRawBuffer();
src_data.destroy();
dst_data.destroy();
const src_img=cv.matFromArray(src_buffer.shape[0], src_buffer.shape[1], cv.CV_8UC3, src_buffer.buffer);
const dst_img=cv.matFromArray(dst_buffer.shape[0], dst_buffer.shape[1], cv.CV_8UC3, dst_buffer.buffer);
// not really sure what this call should look like
cv.resize(src_img, dst_img);
src_buffer.release();
dst_buffer.release();
} |
efeccb3
to
8e4369b
Compare
I see. Are both APIs (destroy & release) suitable for ver 0.16.x ? Btw, I think an automatic garbage-collection mechanism is necessary for pyodide. Manually releasing memory is not friendly to beginners. |
destroy is present in ver 0.16.1 (and much older versions as well). Release is not.
I agree that it is a high priority to improve the GC situation. Unfortunately, browsers have a really poor APIs for destructors. Until July 2020 it was technically impossible to do anything better. With The debugging infrastructure is also very limited: there is no way to request for the browser to perform a collection, which is generally important for debugging destructors. Using |
Sorry for the modification. What about this question: "bytes in Python will be converted to a Uin8ClampedArray array. Then the array is used in JS, so should I release the array after using it?" |
No that uses the previous implicit conversion method. It has lifetime tied to the Python object that it came from. In particular, make sure you have a python reference to the |
From issue #1221 (comment) I found a bug in your proxy-buffer-procs branch:
will break the web worker's rule (cannot access window in web worker) and throws exception when in web workers. You could fix it before PR merge.
is just fine to run. |
Oops, one minute let me fix that. |
I think it should be better now? |
Nope still not working... |
Okay, well |
Thanks! At least the numpy test passes. I'll try to add a few more. |
Nevermind, that specific problem was just me misunderstanding the numpy API. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a couple more numpy tests
packages/numpy/test_numpy.py
Outdated
"np.arange(6).reshape((2, -1))", | ||
pytest.param( | ||
"np.arange(12).reshape((3, -1))[::2, ::2]", marks=pytest.mark.xfail | ||
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The buffer size (and contents) are different in this case. It's likely expected given this implementation where start and endoffsets are recomputed but I wonder if it's something that we want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah this is the expected behavior: if the buffer isn't contiguous the data
field will contain extra entries that are not part of the array. There's no other way to export noncontinuous arrays without copying them.
What does the -1
in the shape mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-1 in reshape means the remaining shape. So for instance np.arange(6).reshape((2, -1))
is identical to np.arange(6).reshape((2, 3))
. It will error if the remaining size isn't an int.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, maybe we could keep this line with a comment but remove the xfail
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will try to modify the test to assert the right thing for noncontiguous buffers.
This reverts commit 5d371c1.
Co-authored-by: Roman Yurchak <rth.yurchak@gmail.com>
This resolves #1202. I added an API
getRawBuffer(type)
to all PyProxies of Python objects that support the Python Buffer protocol. The return value ofgetRawBuffer
is an object with fieldsbuffer
,shape
,strides
,offset
, andrelease
. Theshape
andstrides
are as in the PyBuffer protocol butstrides
has been divided by an appropriate alignment factor. The equivalent ofx[idx0, idx1, ..., idxn]
in python isbuffer[ offset + strides[0] * idx0 + ... + strides[n] * idxn]
.The arguments
buffer
,shape
,strides
,offset
are suitable to be used as the arguments to the constructor for ndarray:https://scijs.net/packages/#scijs/ndarray
e.g.,
release
is a function to call to free the buffer memory (you'll have to destroy the proxy you got it from too though).I think I might add a
readonly
flag to indicate whether the buffer had thereadonly
flag set. This will hopefully fail on any buffer withsuboffsets
(unless they decide to copy themselves inbf_getbuffer
...)@daoxian please let me know what you think.