PPTX to PDF - Memory usage problem

你好,最近又发现内存占用非常大的问题
最新版本:aspose-slides-21.2-jdk16.jar
convert pptx to pdf
源文件:https://app.box.com/s/agjac1uaecus019si9ofk1thjb10n9kn
simple code:
String source=“d:/test/OceanX ECM.pptx”
String dest=“d:/test/OceanX ECM.pptx.pdf”
Presentation ppt = new Presentation(source);
PdfOptions opts = new PdfOptions();
ppt.save(dest, SaveFormat.Pdf, opts)
long total=Runtime.getRuntime().totalMemory();
long free=Runtime.getRuntime().freeMemory();
System.out.println(String.format(“total=%d, free=%d, used=%d”, total, free, (total-free)));
测试结果:
eclipse+windows10
转换时间:1分钟
内存消耗:total=7.3G, free=3.67G, used=3.65G
为什么一个30M的pptx转换pdf竟然需要这么多内存呢?
而且为什么这个内存不能释放呢?

@wilsonsu
很遗憾,我们无法从该站点下载源文件。 请使用其他网站。 例如这个:dropbox.com

抱歉,昨天不小心刪掉了鏈接,麻煩再試下:

@wilsonsu,
感谢您的示例文件。 我向我们的任务管理系统添加了任务 (ID SLIDESJAVA-38467)。 我们的开发团队将调查原因。 纠正此情况后,您会收到通知。

好的,非常感謝 :grin:

You should call GC and dispose() method. Without it, these numbers do not reflect the actual situation of memory consumption. Please check the following code snippet and the results for Xmx4096M:

long start, end;
start = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

Presentation pres = new Presentation("OceanX ECM.pptx");

pres.save("OceanX ECM.pptx.pdf", SaveFormat.Pdf, new PdfOptions());

end = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

System.out.println("Used memory (before GC): " + (end - start));

System.gc();        //call GC
Thread.sleep(1000); //waiting for the GC to finish its work

end = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

System.out.println("Used memory (after GC): " + (end - start));

pres.dispose();

System.gc();        //call GC
Thread.sleep(1000); //waiting for the GC to finish its work

end = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

System.out.println("Used memory (after GC and dispose): " + (end - start));

Used memory (before GC): ~1.4Gb
Used memory (after GC): ~365Mb
Used memory (after GC and dispose): ~94Mb

As you can see, after GC the amount of memory decreased from ~1.4Gb to ~365Mb. Please note that the remaining data (~90MB) is not a memory leak. It contains static data used to speed up the loading and saving of a presentation.

In Aspose.Slides 21.3 the dispose() method will be improved. Also, the size of the data stored in memory will be reduced:
Used memory (before GC): ~1.4Gb
Used memory (after GC): ~365Mb
Used memory (after GC and dispose): ~15Mb

@wilsonsu,
Please let me know if there are any problems or good news on your end.

多謝提示
After GC and dispose, RAM使用量確有減少
我可以每次convert之後,主動執行System.gc()一次

但為何convert需要這麼多RAM,每次convert时,臨時產生的obj已經超過新生代(Young Generation)容量,從而導致進入老年代(Old Generation),因此需要主動GC

如果我Multiple Thread同時convert的話,RAM將會明顯不夠用,Old Generation很快就會OutOfMemoryError

請問,可否控制每次convert時,臨時產生的obj佔用內存不超過1G?
如此,便可以限制臨時產生的obj在新生代(Young Generation)之中,從而**“無”需要**主動GC

@wilsonsu,
The code snippet above demonstrates the actual memory consuming only. You shouldn’t see it as a guide for action. To restrict memory consuming you should use JDK settings. Also, you can set limits to load BLOB objects as follow:

LoadOptions loadOptions = new LoadOptions();

loadOptions.getBlobManagementOptions().setTemporaryFilesAllowed(true);
loadOptions.getBlobManagementOptions().setTempFilesRootPath(tempFilesPath);
loadOptions.getBlobManagementOptions().setPresentationLockingBehavior(PresentationLockingBehavior.KeepLocked);
loadOptions.getBlobManagementOptions().setMaxBlobsBytesInMemory(maxSize);

Presentation presentation = new Presentation(presenationPath, loadOptions);

More details: Manage Blob
API Reference: IBlobManagementOptions interface

Hi, 我已經照足你的sample去做了,似乎沒有任何效果
setTemporaryFilesAllowed(true);
set KeepLocked
甚至:maxSize=100
同樣convert “OceanX ECM.pptx” to pdf
依然使用超過2G內存,並且全部進入Old Generation
看來,我必須要每次主動GC了
但是,實際環境中,很多時候是 Disable Explicit GC !!

@wilsonsu,
Your presentation sample is very large. Please try the next code snippet:

loadOptions.getBlobManagementOptions().setTemporaryFilesAllowed(true);
loadOptions.getBlobManagementOptions().setTempFilesRootPath(tempFilesPath);
loadOptions.getBlobManagementOptions().setPresentationLockingBehavior(PresentationLockingBehavior.LoadAndRelease);
loadOptions.getBlobManagementOptions().setMaxBlobsBytesInMemory(0);

At the moment, memory consumption: memory_consumption.png (23.7 KB)
In future, we will work on memory consumption.

Hi,始終沒有明顯效果
我還是暫時提高JVM的RAM以解決問題先
Thanks