I wanted to understand if you could confirm this is right approach to transform presentation slides this is just an example but overall what I am doing is
- Load presentation into an object
- Save original slides in a place I can retrieve them from and decouple from original presentation
- Transform the slides the way i want (in the example i change the text for the very first slide and copy the others as they are)
- Append transformed slide to final presentation
I am repeating this process 200 times for each slide of the 3 in the original presentation just to exercise the memory issue I am seeing.
The final result is a 70mb presentation in output however memory always increases over time and it never gets released or collected by GC at runtime.
I get to the point where before saving the final result of 600 slides I have close to 23GB memory occupied by the temporary final presentation, understanding that the very final phase which is "saving the file" takes 3 extra GB.
Is this expected? Is there any other otpimization I could take to avoid this issue?
In the final phases of the appending code It gets up to 100mb memory used for each slide i am appending, while in the very first phases it seems that appending a slide is less consuming (seems like to increase in a linear way)
Here's code snippet - you can effectively reproducing with any template in input. Thanks
- Code: Select all
private static void Test1()
{
// Load template presentation
using var templatePresentation = new Presentation();
using var fileStream = File.OpenRead("test.pptx");
templatePresentation.LoadFromStream(fileStream, FileFormat.PPT);
// Initialise result presentation
using var resultPresentation = new Presentation();
resultPresentation.Slides.RemoveAt(0);
for (var i = 0; i < resultPresentation.Masters.Count; i++)
{
resultPresentation.Masters.RemoveAt(i);
}
var originalSlides = new Dictionary<int, ISlide>();
for (var index = 0; index < templatePresentation.Slides.Count; index++)
{
originalSlides.Add(index, templatePresentation.Slides[index]);
}
// Copy properties from template to result presentation
SetPresentationProperties(templatePresentation, resultPresentation);
// Clone slides from source to template with text replacement
for (var index = 0; index < templatePresentation.Slides.Count; index++)
{
var templateSlide = originalSlides[index];
var templateMasterSlideId = templateSlide.MasterSlideID;
var matchingMasterSlide = templatePresentation.Masters.Cast<IMasterSlide>()
.First(masterSlide => masterSlide.SlideID == templateMasterSlideId);
var resultMasterSlideIndex = resultPresentation.Masters.AppendSlide(matchingMasterSlide);
var resultMasterSlide = resultPresentation.Masters[resultMasterSlideIndex];
for (var i = 0; i < 200; i++)
{
Console.WriteLine($"Processing slide {index} ...");
var appendedSlideIndex = resultPresentation.Slides.Append(templateSlide, resultMasterSlide);
var appendedSlide = resultPresentation.Slides[appendedSlideIndex];
if (index == 0)
{
var shape = appendedSlide.Shapes.ToArray()
.First(p => p.Name == "Subtitle 2");
if (shape is IAutoShape autoShape)
{
autoShape.AppendTextFrame($"Slide {i}");
}
}
Console.WriteLine($"Processing slide {index} ... DONE");
}
}
resultPresentation.SaveToFile(@"C:\temp\out.pptx", FileFormat.Pptx2013);
}
private static void SetPresentationProperties(Presentation templatePresentation, Presentation resultPresentation)
{
resultPresentation.SetPageSize(
templatePresentation.SlideSize.Size.Width,
templatePresentation.SlideSize.Size.Height,
true);
resultPresentation.SlideSize.Type = templatePresentation.SlideSize.Type;
resultPresentation.SlideSize.Size = new SizeF(
templatePresentation.SlideSize.Size.Width,
templatePresentation.SlideSize.Size.Height);
resultPresentation.SlideSize.SizeOfPx = new SizeF(
templatePresentation.SlideSize.SizeOfPx.Width,
templatePresentation.SlideSize.SizeOfPx.Height);
resultPresentation.SlideSize.Orientation = templatePresentation.SlideSize.Orientation;
}
See memory consumption in attachment