Closed hbhong closed 10 months ago
The component should clean up all the resources it uses. Components themselves are reference counted, so those should get deleted once the last reference to it is destroyed.
You are on bare metal, right?
The compiler puts the image data in flash. It is possible, using environment variable and linker script to specify what section of the flash the image goes (if that helps)
The Image themselves should not be in RAM so they shouldn't take memory. How did you measure that it was the Image taking memory?
@hunger
The component should clean up all the resources it uses. Components themselves are reference counted, so those should get deleted once the last reference to it is destroyed.
I return the Slint::Image object from the callback, and I just put a debug statement to record which image is returned. and I found the image is only loaded once. if as you said, does it means the component doesn't unload, so the referred image isn't destroyed?
@ogoffart
You are on bare metal, right?
no, the esp-rs provides std and bare metal two implementations, I'm using std crate.
The Image themselves should not be in RAM so they shouldn't take memory.
yes, I just found if I define the image in the slint file, the final image size is more than 9M, but when I return the images from callback function, it reduces to the 3M, What caused the size of the image to decrease?
How did you measure that it was the Image taking memory?
for now , I haven't a tool to check the detail of runtime memory. I just found when I removed the two images (these two image's size are 90X90 pixels and 50X50) from the component, or replace them with 28X28, it doesn't report memory error. So I think the Image
object should use a lot of room in memory.
So when you use EmbedResourcesKind::EmbedForSoftwareRenderer
, the image is stored in flash uncompressed, but is never put in the RAM
If you return it from a callback function, then it is going to be uncompressed in RAM. The image is reference counted. So its memory is freed once no longer in used (no longer stored in a property of a component)
But if you do Image::load_from_path, it will also store the image content in a cache, which is about 5MiB big: https://github.com/slint-ui/slint/blob/6db1c44d2a15bf78b9e819e67560f8f81e6f1ebc/internal/core/graphics/image/cache.rs#L48
There isn't really a way right now to control this cache.
@ogoffart Thank you for your answer, I create the Image
with Image::from_rgba8_premultiplied()
, I think it doesn't put the image into the cache.
For the Slint::Image object, is there a way to release resources, I hope it can be released, and loaded again when the component is loaded instead of keeping them in memory.
The image object uses reference counting behind the scenes, so if you have an Image{}
element in your scene where you want to release the memory it's holding, just set its source to a default constructed slint::Image
. That should replace it with the one you set earlier with Image::from_rgba8_premultiplied()
.
@hbhong are you still seeing this problem? Could you try the workaround of setting an empty image and see if that release your heap pressure?
Please re-open if you can still reproduce the issue. And with more information about how we could also try to reproduce it.
I'm working on a project based on ESP32 C3, which has limited memory, after defining many icons in the slint file, the program can not be compiled and linked. after trying many ways, I found I can load the Image by rust, and return it to Slint with
callback
function. it works, and also my final image file from 9M was reduced to 3M. But there is a new issue, I noticed once the image is loaded by some component, it can not be released anymore, so when I am running some function worked before, it always crash due to memory is not enough.init
function, it is invoked when the component is instantiated, but I don't find a callback to destroy resources.