Memory leak when exporting images

Memory leak when exporting images

nice3point
Advocate Advocate
1,155 Views
11 Replies
Message 1 of 12

Memory leak when exporting images

nice3point
Advocate
Advocate

When calling the ExportImage method, there is a large unmanaged memory spike, this memory is not cleared after the transaction is completed, and remains occupied until Revit closes. Tested versions of Revit 2021-2023

 

Before the call: 1.01 GB

1.png

 

After the call: 2.09 GB

9f6042e11b.png

0 Likes
Accepted solutions (1)
1,156 Views
11 Replies
Replies (11)
Message 2 of 12

jeremy_tammik
Alumni
Alumni

Thank you very much for your report, Roman. The development team may well be aware of this. In order to make sure, I will gladly report it to them for closer analysis. A prerequisite for that is a minimal reproducible case in order to be able to efficiently set up, test and debug the behaviour locally:

 

https://thebuildingcoder.typepad.com/blog/about-the-author.html#1b

 

Are you able to provide that? E.g., maybe an RVT containing a macro plus an image file (or a link to one) to load. Thank you!

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 3 of 12

nice3point
Advocate
Advocate

Simple example to reproduce:

- Revit version: 2023

- Project path: "C:\Program Files\Autodesk\Revit 2023\Samples\rac_basic_sample_project.rvt"

- Profiling tools: JetBrains Rider, dotMemory

 

Code:

 

var sectionType = new FilteredElementCollector(document)
    .WhereElementIsElementType()
    .OfClass(typeof(ViewFamilyType))
    .Cast<ViewFamilyType>()
    .First(x => x.ViewFamily == ViewFamily.Section);

var section = ViewSection.CreateSection(document, sectionType.Id, new BoundingBoxXYZ());
section.DisplayStyle = DisplayStyle.RealisticWithEdges;

var options = new ImageExportOptions
{
    ZoomType = ZoomFitType.FitToPage,
    ExportRange = ExportRange.SetOfViews,
    FitDirection = FitDirectionType.Vertical,
    PixelSize = 220,
    ImageResolution = ImageResolution.DPI_150,
    HLRandWFViewsFileType = ImageFileType.PNG,
    ShadowViewsFileType = ImageFileType.PNG,
    FilePath = Path.GetTempPath()
};

options.SetViewsAndSheets(new List<ElementId> {section.Id});
document.ExportImage(options);

 

0 Likes
Message 4 of 12

nice3point
Advocate
Advocate

@jeremy_tammik  Installer for versions 19-23 and the solution itself. This only happens on first run. All subsequent ones run quickly and without allocating so much memory

0 Likes
Message 5 of 12

jeremy_tammik
Alumni
Alumni

Thank you for further details and a reproducible case. From your description, I can well imagine that this behaviour is intentional. However, I submitted the ticket REVIT-193325 [doc.ExportImage memory leak] for the developers to take a closer look.

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 6 of 12

nice3point
Advocate
Advocate

I don’t know whether it was intentional or not, but I don’t want them to take a couple of gigabytes of memory from me to export an 8 kilobyte image)

Message 7 of 12

jeremy_tammik
Alumni
Alumni

Yes, I understand. There may be other important considerations that we are unaware of. I added your comment to the ticket, anyway.

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 8 of 12

Sean_Page
Collaborator
Collaborator

Do you think this is Revit causing this, or the GetFiles method indexing files looking for matches to return?

 

Since you know the file path can't you just return it directly?

Sean Page, AIA, NCARB, LEED AP
Senior Partner, Computational Designer, Architect
0 Likes
Message 9 of 12

nice3point
Advocate
Advocate
The breakpoint does not capture this method, and I have attached a zip archive with a solution where this method does not exist at all
0 Likes
Message 10 of 12

RPTHOMAS108
Mentor
Mentor

Some objects such as ImageExportOptions, Document and UIApplication Inplement IDisposable.

 

Have you tried calling Dispose on such? Ideally you should not need to but in theory GC has no knowledge of items on the unmanaged side, the dispose method is meant to be implemented to deal with those when called (also called inherently at the end of 'using' block).

 

Although it would be a bit ridiculous calling Dispose on every API object we use so instead:

 

Object.Finalize should have also be overridden (or SafeHandle used) by the Autodesk API developers to deal with the unmanaged resources associated with a managed object prior to natural destruction of the managed part i.e. Finalize is always called prior to GC destroying the managed part (dispose isn't). So would assume something lacking in that area needs looking at and perhaps in meantime dispose could help.

 

Not many code samples you see would be using a 'using' block with the Document object or calling dispose after using it. So more guidance is needed in that respect if 'Dispose' is expected to be called by the developer (on which objects)? Definitely transactions that is clear but what other objects that implement IDisposable?

 

 

0 Likes
Message 11 of 12

nice3point
Advocate
Advocate
Memory leak in the ExportImage method itself, and not when creating an object, the method returns void and I can’t influence its work in any way. Disposing ImageExportOptions does nothing
0 Likes
Message 12 of 12

jeremy_tammik
Alumni
Alumni
Accepted solution

Analysis completed.

  

REVIT-193325 [doc.ExportImage memory leak] closed as 'code fix needed'.

  

REVIT-193708 [doc.ExportImage memory leak] raised for critical development work.

  

Thank you for raising this!

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open