Skip to content
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 RGBMatrix::DeleteFrameCanvas(FrameCanvas*) #1456

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

SolidHal
Copy link
Contributor

And associated python bindings

Enables the user to direct the RGBMatrix to free FrameCanvas
objects to avoid wasting memory

And associated python bindings

Enables the user to direct the RGBMatrix to free FrameCanvas
objects to avoid wasting memory
@hzeller
Copy link
Owner

hzeller commented Aug 21, 2022

Is there a particular use-case you encountered where you need that ?

Having a DeleteFrameCanvas method encourages programming patterns to use canvases in a way that goes beyond double or triple buffering off-screen canvases are meant for, so I would need some convincing.

@SolidHal
Copy link
Contributor Author

The simplified description of my use case is that I am buffering multiple gifs offscreen in an async manner. The "producer" adds some informational overlays (time, weather, etc) and creates a FrameCanvas for each frame in the gif and throws the set of canvases on a queue.
This keeps the "consumer" function fast since it just needs to pull a set of canvases (which correspond to a gif) from the queue and call SwapOnVsync on each canvas in the set. Since each gif is different length, reusing canvases would complicate things further, which means over time the memory consumption goes through the roof.
The simple solution is to not reuse canvases, and instead allocate/delete them as needed.

@hzeller
Copy link
Owner

hzeller commented Aug 21, 2022

Did you consider the content streamer ?
It is meant for this use-case. The led-image-viewer uses that for that very purpose: pre-processing GIFs and other animations.

This format can be stored in memory (what the image viewer does) or even on disk: the video-viewer
has a mode to output to a stream on disk so that it can be fast replayed later without the video decoding overhead.

The reason why creating and deleting frame-canvases is problematic is that they are exceeding the cache size of the Pi, so if you have many of them, cycling through them means they come in 'cold' from the (rather slow) DRAM, resulting in inconsistent frame-rates up to visible flicker.

If we only have a few FrameCanvas'es, they can stay in Cache, so the main loop that has to read in a high rate can do so without interruptions. It is cheaper to copy data into an existing FrameCanvas using content streamer than having a FrameCanvas coming in cold from DRAM.

@SolidHal
Copy link
Contributor Author

SolidHal commented Aug 22, 2022

Thanks for the pointers, I hadn't considered the content-stream. Took at look at the content streamer, and led-image-viewer.

I think I could implement something like that on the python side that would work for my use case. The complication being that I also need to be able to interrupt the current stream of gif frames to display frames from other producers (ex: right now I have it showing album art when music start playing) but I can think of a few ways to do that.

It is cheaper to copy data into an existing FrameCanvas using content streamer than having a FrameCanvas coming in cold from DRAM.

This makes some sense, since we are just copying the frame data, and none of the FrameCanvas objects overhead from DRAM -> cache, but its surprising to me that the objects overhead is so large that it causes framerate issues.

I'll expose Serialize & Deserialize on the python bindings and go from there.

this enables usage like in cpp content-streamer
@SolidHal
Copy link
Contributor Author

I opened #1457 with the Serialize/Deserialize bindings
in my testing, I don't observe any performance gains from using them over creating/deleting canvases directly.

I would guess that because of all of the overhead from python, and the additional async tasks I have running, the canvas objects we really care about don't hang around in the rpis cache long enough anyway :/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants