Closed define-private-public closed 7 years ago
Also, I don't know too much about Python's GC, and how CFFI works with it when doing those new()
calls, but I noticed that this program was slowly eating up more and more RAM when running, with no signs of decreasing. When I turned off of the preview, I noticed that it wasn't creeping up anymore.
I don't think it's my PyQt code, though I could be wrong.
My suspicions were correct, it was from the get_preview()
code and the CFFI new
allocations. With the one above, my system would jump from 0.6% memory usage to about 6% in five minutes.
I switched the code out with this:
camfile_p = gpFFI.new('CameraFile **')
gpLIB.gp_file_new(camfile_p)
data_p = gpFFI.new('char **')
length_p = gpFFI.new('unsigned long *')
def get_preview(cam):
gpLIB.gp_camera_capture_preview(cam._cam, camfile_p[0], cam._ctx)
gpLIB.gp_file_get_data_and_size(camfile_p[0], data_p, length_p)
return gpFFI.buffer(data_p[0], length_p[0])[:]
After running the program for about 10 minutes memory usage flatlined at 0.6%.
I'm pretty sure there are other parts in the Camera
wrapper that are making many more new
allocations than needed. It would be best to give the Camera
class some internal CFFI buffers so the methods themselves aren't doing the allocations; but that should be it's own separate ticket.
Thank you for the analysis! I was pretty inexperienced with CFFI when I wrote the code.
However, regarding your question:
Also, I don't know too much about Python's GC, and how CFFI works with it when doing those new() calls, but I noticed that this program was slowly eating up more and more RAM when running, with no signs of decreasing.
According to the CFFI docs, the underlying memory should be freed once the Python variable goes out of scope. Seems like this is not the case for the camfile_p
and data_p
, though :-/
I'm not sure when I'll be able to get to making the necessary changes, but you're welcome to submit a pull request, and I promise that I won't take as long for merging it as it took me to respond to this issue (sorry) ;-)
I might go ahead and do this soon enough, but not immediately.
As stated before, this might be a little more complex of a cleanup since I think there are a lot more memory leaks in Camera
that need to be dealt with (.e.g, I think it's present for each time a picture is taken).
I think it would be best to first do an audit of where the leaks are.
Might be a good idea to set up a testing script that runs through all exposed functionality with real hardware and then run that through valgrind.
https://github.com/jbaiter/gphoto2-cffi/blob/master/gphoto2cffi/gphoto2.py#L748
images that are returned from
gp_camera_capture_preview()
are meant to by tiny preview images, that can captured many times per second (e.g. 30 captures per second) to provide a sort of live feed from the camera.The
Camera.get_preview()
method is functionally correct, except that the decorator@exit_after
will put the camera in a state where it can't successively capture preview images.Take this code snippet for example
When pressing
P
, it will create a live camera feed, using theget_preview()
that I defined at the top of the file.Please remove the decorator from
Camera.get_preview()
. Is there some extra cleanup function that should be called for when to turn a preview off?