Making inkscape usable in valgrind grumble
Hi all,
In order to find memory leaks, some types of access violations, and the use of uninitialized variables I depend on valgrind. The problem is that valgrind is barely usable with Inkscape. The output on even the most minimal session (open, type a few letters, format them, close) runs to just under 500K lines and takes 5 minutes to complete. Some of this may be because garbage collection must be turned off in order to use valgrind. That is:
export _INKSCAPE_GC=disable; valgrind .... src/inkscape
There is no choice in that though, because if it is not done valgrind crashes when it tries to run inkscape. (Ubuntu 12.10.4, 32 bit, current Trunk). There is a libgc.supp in the top of the distribution, but it cannot be used on my system, since it does not suppress valgrind's crash when it tries to run inkscape with GC enabled.
Here is the damage seen on a normal exit for a minimal run:
==16527== LEAK SUMMARY: ==16527== definitely lost: 567,697 bytes in 17,670 blocks ==16527== indirectly lost: 2,167,402 bytes in 73,234 blocks ==16527== possibly lost: 21,940,610 bytes in 282,461 blocks ==16527== still reachable: 21,470,100 bytes in 360,304 blocks
What can be done so that Inkscape makes a better effort at cleaning up its enormous memory tangle when it exits while running in valgrind? Some of the memory Inksape allocates is cleaned up, but it seems like a very high percentage of memory allocations are tacked into this complex memory structure, and inside valgrind the whole ball of yarn is just dropped on the floor when the program reaches the final exit(), rather than being unwound in an orderly fashion. (In theory GC may be cleaning this up better, but I'm not sure how we can really know, since valgrind cannot tell us.)
Could somebody who understands these parts of Inkscape PLEASE clean up this mess, so that in future when "_INKSCAPE_GC==disable" Inkscape will unwind its memory structures before exiting? At the very least we will learn after this unwinding what memory is still left, and that will be the result of existing bugs in the code. Once we obtain a baseline inkscape that is usable once again in valgrind, we can reasonably expect that by using valgrind developers will be able to catch the memory problems they may introduce. Sadly that is far from true now, what with so many thousands of lines of background noise in the log files to slog through.
Admittedly some of the lines in valgrind's log file do come from valgrind issues, but the ones I know about can be removed with:
cat >wcslen_sse2.supp <<EOD { wcslen1 Memcheck:Addr8 fun:__wcslen_sse2 fun:* } { wcslen2 Memcheck:Cond fun:__wcslen_sse2 fun:* } { iffyinflate Memcheck:Cond fun:inflateReset2 fun:inflateInit2_ obj:* } EOD valgrind -v --leak-check=yes --leak-resolution=high --num-callers=15 --show-reachable=yes --suppressions=./wcslen_sse2.supp --log-file=/tmp/vgfi.log src/inkscape
which improves the output to: --16527-- used_suppression: 208319 wcslen1 --16527-- used_suppression: 142 wcslen2 --16527-- used_suppression: 330 iffyinflate ==16527== ==16527== ERROR SUMMARY: 97190 errors from 13437 contexts (suppressed: 208791 from 656)
I understand that there may be other problems in some libraries which are called, but from the contents of the log file it looks like the majority of the loose ends were directly created in Inkscape. (And we can use valgrind suppression files, as above, to silence the unfixable library problems.)
Thanks,
David Mathog mathog@...1176... Manager, Sequence Analysis Facility, Biology Division, Caltech
2014-02-04 mathog <mathog@...1176...>:
Hi all,
In order to find memory leaks, some types of access violations, and the use of uninitialized variables I depend on valgrind. The problem is that valgrind is barely usable with Inkscape. The output on even the most minimal session (open, type a few letters, format them, close) runs to just under 500K lines and takes 5 minutes to complete. Some of this may be because garbage collection must be turned off in order to use valgrind. That is:
export _INKSCAPE_GC=disable; valgrind .... src/inkscape
There is no choice in that though, because if it is not done valgrind crashes when it tries to run inkscape. (Ubuntu 12.10.4, 32 bit, current Trunk). There is a libgc.supp in the top of the distribution, but it cannot be used on my system, since it does not suppress valgrind's crash when it tries to run inkscape with GC enabled.
In the long term, I think the consensus is that we should move away from garbage collection and towards explicit memory management with smart pointers. In the short term, I'm afraid there is little we can do about this. The initial pieces of the puzzle are already in place with the C++ification work on the SP tree.
Here is the damage seen on a normal exit for a minimal run:
==16527== LEAK SUMMARY: ==16527== definitely lost: 567,697 bytes in 17,670 blocks ==16527== indirectly lost: 2,167,402 bytes in 73,234 blocks ==16527== possibly lost: 21,940,610 bytes in 282,461 blocks ==16527== still reachable: 21,470,100 bytes in 360,304 blocks
What can be done so that Inkscape makes a better effort at cleaning up its enormous memory tangle when it exits while running in valgrind? Some of the memory Inksape allocates is cleaned up, but it seems like a very high percentage of memory allocations are tacked into this complex memory structure, and inside valgrind the whole ball of yarn is just dropped on the floor when the program reaches the final exit(), rather than being unwound in an orderly fashion. (In theory GC may be cleaning this up better, but I'm not sure how we can really know, since valgrind cannot tell us.)
GC is mainly used in code related to XML and undo handling. Removing GC there requires modifying every piece of code that creates or deletes XML nodes - at least 277 places according to grep.
Regards, Krzysztof
Hi
On 04/02/14 05:01, Krzysztof Kosiński wrote:
2014-02-04 mathog <mathog@...1176...>:
Hi all,
In order to find memory leaks, some types of access violations, and the use of uninitialized variables I depend on valgrind. The problem is that valgrind is barely usable with Inkscape. The output on even the most minimal session (open, type a few letters, format them, close) runs to just under 500K lines and takes 5 minutes to complete. Some of this may be because garbage collection must be turned off in order to use valgrind. That is:
export _INKSCAPE_GC=disable; valgrind .... src/inkscape
There is no choice in that though, because if it is not done valgrind crashes when it tries to run inkscape. (Ubuntu 12.10.4, 32 bit, current Trunk). There is a libgc.supp in the top of the distribution, but it cannot be used on my system, since it does not suppress valgrind's crash when it tries to run inkscape with GC enabled.
In the long term, I think the consensus is that we should move away from garbage collection and towards explicit memory management with smart pointers. In the short term, I'm afraid there is little we can do about this. The initial pieces of the puzzle are already in place with the C++ification work on the SP tree.
Here is the damage seen on a normal exit for a minimal run:
==16527== LEAK SUMMARY: ==16527== definitely lost: 567,697 bytes in 17,670 blocks ==16527== indirectly lost: 2,167,402 bytes in 73,234 blocks ==16527== possibly lost: 21,940,610 bytes in 282,461 blocks ==16527== still reachable: 21,470,100 bytes in 360,304 blocks
What can be done so that Inkscape makes a better effort at cleaning up its enormous memory tangle when it exits while running in valgrind? Some of the memory Inksape allocates is cleaned up, but it seems like a very high percentage of memory allocations are tacked into this complex memory structure, and inside valgrind the whole ball of yarn is just dropped on the floor when the program reaches the final exit(), rather than being unwound in an orderly fashion. (In theory GC may be cleaning this up better, but I'm not sure how we can really know, since valgrind cannot tell us.)
GC is mainly used in code related to XML and undo handling. Removing GC there requires modifying every piece of code that creates or deletes XML nodes - at least 277 places according to grep.
As far as I understand one option could be adding a environment variable, something like DISABLE_GC or similar, then, as far as i know, to surround all the Inkscape::GC::XXX with #ifndef #endif.
Not sure if this would be a correct way to proceed and disable the garbage collector properly. I did a very small test, where i commented the calls to sp_main_gui and sp_main_console and also commented the Inkscape::GC::Init() line. Before commenting the GC init line, a few errors related to GC appeared when running valgrind, after commenting it, the errors disappeared.
Is that approach correct ? Or am i missing something here ?
Regards, Krzysztof
Managing the Performance of Cloud-Based Applications Take advantage of what the Cloud has to offer - Avoid Common Pitfalls. Read the Whitepaper. http://pubads.g.doubleclick.net/gampad/clk?id=121051231&iu=/4140/ostg.cl... _______________________________________________ Inkscape-devel mailing list Inkscape-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/inkscape-devel
Cheers. Guiu.
On Tue, Jun 3, 2014, at 04:45 AM, neandertalspeople wrote:
As far as I understand one option could be adding a environment variable, something like DISABLE_GC or similar, then, as far as i know, to surround all the Inkscape::GC::XXX with #ifndef #endif.
Not sure if this would be a correct way to proceed and disable the garbage collector properly. I did a very small test, where i commented the calls to sp_main_gui and sp_main_console and also commented the Inkscape::GC::Init() line. Before commenting the GC init line, a few errors related to GC appeared when running valgrind, after commenting it, the errors disappeared.
Is that approach correct ? Or am i missing something here ?
That would disable the garbage collection, however it would then leave all the objects in memory and not collected at all. Essentially all allocated items would be left to dangling pointers... that is they would get new'ed and then forgotten so that they are never freed.
A better approach for now would be to look for objects left in memory that you would expect to have been cleaned up and then work your way up the ownership chain to see what is being held onto. Our document object might be a higher up place to start. Adding a g_message() in the ctor and dtor can help, and a static count per class too. Many of the objects that are not using the garbage collector *should* be cleaned up per normal Gtk/Gtkmm destruction, but accidental retention of a parent is blocking that. I believe there is some low-hanging fruit that the simple debug-dump approach can catch quickly.
In general Gtk+ and Gtkmm have clear ownership rules, and if we switch the remaining items from gc to follow those rules instead we should be good. Some of this will be via smart pointers, but other items need to just follow Gtkmm (including the manage() wrapper call).
participants (4)
-
Jon A. Cruz
-
Krzysztof Kosiński
-
mathog
-
neandertalspeople