memory leaks associated with images

Bug #986271 reported by David Mathog on 2012-04-20
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Inkscape
Medium
David Mathog

Bug Description

This was tested on Windows XP with code built from Trunk downloaded 2/29/2012.

There are at least two locations where image (bitmap) operations leak memory. This can be seen with the Windows task manager tool.

A) Extract image extension:
1. Select a bitmap
2. extendions -> images -> extract image
3. save the image
The memory usage increases at step 3 and does not return to the level it was at (1).

B) Above whatever calls the save as "::image" method if one is implemented for EMF (I am currently working on this, and traced the observed memory leak to outside of my changes):
1. Change emf-win32-print.cpp by adding:

unsigned int PrintEmfWin32::image(Inkscape::Extension::Print * /* module */, /** not used */
                           unsigned char *px, /** array of pixel values, Gdk::Pixbuf bitmap format */
                           unsigned int w, /** width of bitmap */
                           unsigned int h, /** height of bitmap */
                           unsigned int rs, /** row stride (normally w*4) */
                           Geom::Affine const &tf_ignore, /** WRONG affine transform, use the one from m_tr_stack */
                           SPStyle const *style) /** provides indirect link to image object */
{
  return 0;
}

2. btool
3. start inkscape and open an SVG containing a single 1280 x 1024 bitmap.
4. save as -> emf
memory leaks 11M relative to what it was at (3), or about 2X the size of the bitmap which was passed into the image method (but not processed).

In my working code (which does save images) I was able to reduce the leakage somewhat by free(px) at the end of the routine. When that is in place the first call leaks around 5M (probably one full bitmap) and then each subsequent call leaks another 300K (roughly).

In an unrelated bug, the transform passed to PrintEMFWin32::image is incorrect, the one from m_tr_stack gives the correct geometrical transformations with: point * transform.

The size of these memory leaks is pretty darn large, anybody who makes heavy use of these features is going to find
inkscape burning through a lot of memory.

Kris (kris-degussem) wrote :

A confirmed on windows vista 64 bit, trunk revision 11265, devlibs revision 29.
Roughly 66 MB is leaked every time with the given procedure.

Changed in inkscape:
status: New → Confirmed
importance: Undecided → Medium
Kris (kris-degussem) on 2012-04-20
tags: added: exporting extensions-plugins performance win32
Kris (kris-degussem) wrote :

Saving an svg (containing one 16 MP bitmap) to emf eats also some 60-64 MB which is not returned.

David Mathog (mathog) wrote :

Here is another issue, possibly related:

1. Start Inkscape ("new document", nothing in it). Size: 58.9M
2. Minimize the window. Size: 3.6M
3. Restore the window: 9.6M <------ 50M less!!!!
4. Import a 1280 x 1024 PNG (size about 5M in RGBA format). Size; 43M
5. Minimize the widnow. Size 5.5M
6. Restore the window. 11.5M <----31.5M less!!!
7. Select the image and delete it. Size 18.3M
8. Minimize the window. Size: 2.8M
9. Restore the window. Size: 13.7M

This was again on XP with Trunk, but 0.48.2 seems to do the same things.

There is some really strange stuff going on here. Why would importing one image add ~34M to the used memory? Should be 5M for an RGBA (assuming one is kept around) and around 300K for the PNG encoded base64 version in the XML. What
about the other 29M?

Kris (kris-degussem) wrote :

I have no idea what it does, but the code suggested in bug description part B seem to fix this memory leak. Commited in trunk revision 11268. So part B / comment 2 should be fixed now. Thanks a lot for sharing this code.

Assigning the bug to you, David.
If you might have any other ideas, please add the patches or files as attachment.

Changed in inkscape:
assignee: nobody → David Mathog (mathog)
Kris (kris-degussem) wrote :

I have not checked comment 3, though from the description it seems to me completely unrelated. It is best for the future to report issues that are probably unrelated (or when you doubt) in separate bugs.

David Mathog (mathog) wrote :

The little bit of code in part B was a stub routine that does nothing but replace another virtual method in,

src/extension/implementation/implementation.h

(I do not pretend to understand how this is all screwed together, it took days to figure out that adding PrintEmfWin32::image
would override the virtual method in that header file. I still have no idea what method/function actually calls the emf image method, since gdb bt failed to resolve it.)

The real code (which should work as well) is the EMF input changes just posted for bug 818539.

Unfortunately I cannot run valgrind in mingw, so I have no decent tool with which to track down these leaks. It looks like the only other option is mpatrol, which has to be linked in statically. (Never used it.) If these leaks are also present in the linux version then it would be _much_ easier to run them down there.

jazzynico (jazzynico) on 2012-05-10
Changed in inkscape:
status: Confirmed → Triaged
David Mathog (mathog) wrote :

Finally was able to work on inkscape on linux (Ubuntu 12.04LTS) where the tools are better. The attached patch fixes the core issue with the memory leak (for all image saves, not just EMF). The free() which was placed in the emf-win32-print.cpp should be removed when this patch goes in.

As a side note, even with this patch, the virtual memory still rises on each EMF save that includes images, just not as much.
With valgrind I could not determine, beyond the leak plugged with the above patch, exactly where this was happening. Most frustrating. To use valgrind at all it was necessary to add to default.supp:

{
   <wcslen1>
   Memcheck:Addr8
   fun:__wcslen_sse2
   fun:wcscoll
}

{
   <wcslen2>
   Memcheck:Cond
   fun:__wcslen_sse2
   fun:wcscoll
}
{
   <iffyinflate>
   Memcheck:Cond
   fun:inflateReset2
   fun:inflateInit2_
   obj:*
}

(To eliminate a zillion warnings on wslen_sse3). Run like this:

 export _INKSCAPE_GC=disable
 valgrind --leak-check=full --num-callers=50 src/inkscape >/tmp/foo 2>&1

It was incredibly, painfully, slow. Minutes to open a window. Anyway, open an SVG with some images, save it as EMF (with images) twice, exit. This produced an output file with 23000 loss records, 400K lines and 43MB in size and ending with:

==9760== LEAK SUMMARY:
==9760== definitely lost: 251,061 bytes in 8,668 blocks
==9760== indirectly lost: 1,686,567 bytes in 27,444 blocks
==9760== possibly lost: 31,758,052 bytes in 262,250 blocks
==9760== still reachable: 12,257,891 bytes in 23,151 blocks
==9760== suppressed: 0 bytes in 0 blocks

The problem being that the memory leaks associated with image operations seem to be in the "possibly lost" and "still reachable" categories. (It also doesn't help that the call stack has been observed as being up to 65 levels deep in gdb - sometimes there may be such a thing as too much abstraction!)

jazzynico (jazzynico) wrote :

Patch from part B committed revision 11268.

David, is it ok to apply your patch from comment #7 (and update emf-win32-print.cpp) and then close the report?
Or do you still have improvements in progress?

Changed in inkscape:
milestone: none → 0.49
status: Triaged → In Progress
su_v (suv-lp) wrote :

@JazzyNico - could you review the proposed related change which had been part of the larger omnibus patch (bug #988601)?

See here:
<http://bazaar.launchpad.net/~inkscape.dev/inkscape/lp988601/revision/11669#src/sp-image.cpp>

It has been reverted in that branch today, to keep its focus on EMF input/output support as much as possible.

Kris (kris-degussem) wrote :

Fix committed in trunk revision 12482.
Thanks for the patch David.

Changed in inkscape:
status: In Progress → Fix Committed
tags: added: bitmap
removed: exporting win32
Adgenodux (tempo-data) wrote :

Around same issue under 0,48.

- Open new empty document
- import 4x 4000x3000dpi 3,98Mb JPG pictures (34,8Mb BMP)
---> Inkscape RAM use jumps from 70Mb at start to 734Mb after pictures import
- resize pictures to 800x600dpi
---> Inkscape RAM use remain above 700Mb
- erase 2 pictures
---> Inkscape RAM use remain above 700Mb
- save SVG file (23,8Mb)
---> Inkscape RAM use remain above 700Mb
- export the 2 just merged remaining pictures to Bitmap (400k)
- erase entire sheet
---> Inkscape RAM use remain above 700Mb
- open new empty document keeping the previous open
- close the previous document, keep the just new opened one
---> Inkscape RAM use remain above 700Mb

Must close completly Inkscape and open it again...

Seems memory not correctly cleaned...

Changed in inkscape:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers

Bug attachments