-
Notifications
You must be signed in to change notification settings - Fork 57
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
Memory leak when destroying a surface #225
Comments
How do you measure the memory usage (leak) and why are you sure, that's the surfaces? |
Measured with Task Manager on Windows and htop on Linux. The surfaces are the only objects being created, and the actual code would have bigger issues if |
A 512x512 ARGB surface should be around 1MB, so the 50M on windows shows already a reduction from your 20000 instances and the 2.7GB in linux might be the full set of allocations. I'm currently away from my development box, so I cannot test if this is reproducible but some people reported similar issues when both a destroy call and a finalizer call is defined. Overall libcairo has its own memory management based on reference counting and based on system calls and in linux it can happen that 'freed' memory shows up as allocated until new allocation. But I'm no expert here. btw: could you explain a little bit what your code tries to do? in libcairo surfaces are more output devices than intermediate data and resizing is actually not a defined operation. |
I am using multiple Cairo surfaces (as layers) and drawing the combination of them onto a GTK Surface. Many of the operations requires me to actually redraw the whole canvas, instead of just doing small redraws the last drawing operation. The GTK Surface is essentially just a "viewpoint" of the layers, but the size of the complete render might need to change sizes due to user input. I'm not familiar with Cairo, and could not seem to find any methods that reset the surface back to the "newly instantiated" state. The reason I haven't looked to much into actually reseting the surface is because the program would leak memory either way, if the user was too request a differently sized complete render. Some actions of the program therefor produce a huge amount of canvases (that are being destroyed from my code in the same way as above) for repainting, and while this is almost fine on Windows (memory usage slowly goes up, resets, goes up higher than before, so its still "leaking") it is exponentially worse on Linux and never seems to be freed, leading to all memory being consumed after a few minutes. |
For what it's worth, I can easily reproduce this issue on my linux machine using the provided sample code. |
Testing repeated mass creation and deletion of surfaces on windows with the information in the original comment seems to actually not be leaking, and is freed properly. using Cairo
while true
l = [CairoARGBSurface(512, 512) for i in 1:10000]
destroy.(l)
gc()
Cairo.GC.gc()
end However it doesn't look like its freed at all on Linux. Maybe the issue is Linux / Cairo version specific? |
As written above, I cannot test code right now and I would doubt, that libcairo has some inbuilt memory problems on linux systems. And the the same thing could be tested in C. For handling layering in Cairo, some time ago I wrote an interactive tool with pygtk/pycairo and I used also image surfaces as intermediate drawing area, I just allocated them big enough (screen size) and did reset by just filling the surface with color 0,0,0,0 = RGBA. I don't know the steps to clear vector surfaces. maybe they have to be destroyed/recreated. A lot of drawing operations - especially in updates can be handled by proper clipping, this is one of the USPs of Cairo. |
Filling the layers with (0, 0, 0, 0) (with the correct operators set) seems to be working fine. The problem is that the surface can literally be any size, and not limited by window/screen size. A workaround I could do is cache NxN surfaces and double them in size when needed, but that seems like a dirty hack to work around the problem. Thanks for the help though, it's way less violent on Linux now. I'm not familiar with the GDB stuff you mention though. I'll keep the issue open so somebody that knows what they are doing can actually debug and fix the problem. |
I spend yesterday some minutes on that, could reproduce a bigger memory impact on linux (but only on VIRT) and could see the destroy calls on gdb. I'll look into this again, but i looks like an observer side problem -> the memory isn't complete freed, but is not allocated in the sense you cannot use it. |
Short update. I tested this today and can reproduce it on 0.6.4 but not on 1.0.0. |
destroy()
on surface (CairoARGBSurface
, to be exact) doesn't seem to get removed properly.This is tested on windows running
and Linux with
Cairo.VERSION v"0.6.2"
andv"0.6.0"
.This is far worse on Linux where this uses 2.7GB of RAM after running the snippet, but only seems to add 50MB on windows. Either way it just keeps leaking on both of them (when making new surfaces later on down the road).
Is there any obvious way to fix this? The reason this happens in my code is because I need to reset or resize surfaces. Remaking the surface has been the least painful way to get this done for now, but leads to this problem. From what I can see in the source code the resize function for surfaces is also commented out, so I'm guessing this problem has been encountered for sane usages as well?
The text was updated successfully, but these errors were encountered: