Aspose.PSD issue with particular photoshop document

Hello.
I will start with saying that our company uses Aspose.PSD to access TextLayers inside photoshop files, changing/replacing Portions from them, and other manipulations.

We have recently hit a situation where a particular document uses (in our opinion) way too much memory, and takes way too long to access every textLayers and change them, to the point where we have application crashing due to it.

I have made an experiment using versions 23.11, 24.6 and 24.7, and used a simple console app that
accesses said document 10 times, where each time it adds a new simple Portion to every single TexTLayer found inside it.

The code is as follows:

public static void Main()
{
SetupPathing();
for(int i = 0;i<10;i++)
{
TestPSD(i);
}

Console.Read();

}

private static void SetupPathing()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
psdFilePath = “/app/PSD.psd”;
psdSavePath = “/app/PSDSaveResult.psd”;
}
else
{
psdFilePath = “PSD.psd”;
psdSavePath = “PSDSaveResult.psd”;
}
}

private static void TestPSD(int index)
{
var image = Image.Load(psdFilePath);
PsdLicenser.LoadLicense();

if (image is PsdImage psdImage)
{
    foreach (var layer in psdImage.Layers)
    {
        if (layer is TextLayer textLayer)
        {
            Stopwatch w = Stopwatch.StartNew();

            var newPortion = textLayer.TextData.ProducePortions(
            new[] { "adding text" },
            null ,
            null
            ).First();


            textLayer.TextData.AddPortion(newPortion);
            textLayer.TextData.UpdateLayerData();
            w.Stop();
            Console.WriteLine($"Portion added, time: {w}");
        }
    }
    var imageOptions = new PsdOptions(psdImage);
    psdImage.Save($"{psdSavePath}+{index}.psd" , imageOptions);
    Console.WriteLine($"Document {psdSavePath}+{index}.psd saved.");
}

}

Running this code under docker linux, and also under windows, causes some textLayers to take even 10+ seconds to process, some more than 50 seconds sometimes under linux.
the memory under docker looks like this:

image.png (29.0 KB)

Runnin it on windows, i see the following:
image.png (16.1 KB)

I’m not sure what to call it, but the trend appears to be a memory leak somewhere caused by this document, or something of the sort.

Using other photoshop documents the trend is not visible, and works pretty much as we expected, but in this particular case, it does not.

Can you please check why/if this document is to blame? Or if you have any ideas for me to try, but currently, if this simple code sample is causing these issues, you can imagine what is happening when we further manipulate TextLayers in our application.

I have uploaded the document, as well as my DockerFile used in the app to test on linux with Docker:
https://drive.google.com/drive/folders/1lb2XPJsFYQ3f3cNGeBqeNEqrRthOUsox

Thank you and hope to hear from you soon!

@IBurzoEvoRWS

Thank you for your extensive investigation or memory usage and for files for reproducing this issue. At this moment, Aspose.PSD team actively works on Memory Usage Optimization. The file is quite big, and the processing of PSD Images is RAM-Demanding operation. Team works on implementation of more optimized way to process big images. Hope, your report will help in optimization process. I’ve set high priority on the investigation of this case.

We have opened the following new ticket(s) in our internal issue tracking system and will deliver their fixes according to the terms mentioned in Free Support Policies.

Issue ID(s): PSDNET-2130

You can obtain Paid Support Services if you need support on a priority basis, along with the direct access to our Paid Support management team.

Hello!

I appreciate the quick response and happy to hear the issue is being actively worked on.
Thank you, and hope to see a new version soon :smiley:

@IBurzoEvoRWS
I tested your code and got somewhat similar results, however when I dispose the image after use, the memory usage stabilized and stopped growing so strongly.
I recommend using a using statement for your var image in the TestPSD method, like this:

using (var psdImage = (PsdImage)Image.Load(psdFilePath))
{
}

or add the following code at the end of the TestPSD method:

image.Dispose();
image = null;

Please try this recomendation and send me your results.

Hello!
Our “original” code does indeed dispose and then make the image null, just like in the last code you provided.

(In our business logic) We load the PsdImage in memory, update the layers in it as required, and then at the end we save the image, and dispose it. This is how our code works, more or less.
We have documents with 60-90 layers, even more in some cases.

We tried recently an experiment where we load the image and save it every single time we update a layer, with "using"s , and even though the memory use is a bit better, the mere fact of opening/saving every time made our execution times way longer, which upon further testing, is unacceptable.

The experiment failed and as such we are reverting to our initial implementation, where we open the PsdImage at the start, update layers in it, and when we “complete”, we dispose and set it as null.

If you have other ideas, please let me know, as currently this will not work for us.

Thank you!

@IBurzoEvoRWS unfortunately we were unable to repeat the issue. Could you please provide the correct code with all disposed images and the input file where this can be reproduced?
We tried the code code above and issue was reproduced, but the RAM issues were fixed after the correct disposing. Or maybe you have other file that has the described problems?

Hello @Dmitriy.Sorokin .
I have updated my console app to better reflect the issue, and i am using the Dispose variant instead of “using” to better reflect our current implementation.

image.png (39.2 KB)

This is how the mem use looks toward the end, when the saving happens of the PsdImage.
It has leaps from usual 500mb to 2Gb+, even 3Gb+ sometimes.
The code is as follows:

private static void TestPSD(int index)
{
var psdImage = (PsdImage)Image.Load(psdFilePath);
foreach (var layer in psdImage.Layers)
{
if (layer is TextLayer textLayer)
{
Stopwatch w = Stopwatch.StartNew();

        var newPortion = textLayer.TextData.ProducePortions(
        new[] { "adding text" },
        null,
        null
        ).First();

        textLayer.TextData.AddPortion(newPortion);
        textLayer.TextData.UpdateLayerData();
        w.Stop();
        Console.WriteLine($"Portion added, time: {w}");
    }
}
var imageOptions = new PsdOptions(psdImage);
var psdSaveName = $"{psdSavePath}({index}).psd";
Stopwatch w2 = Stopwatch.StartNew();
psdImage.Save(psdSaveName, imageOptions);
w2.Stop();
Console.WriteLine($"Document {psdSavePath}({index}).psd saved. Time it took to save: {w2}");
psdImage.Dispose();
psdImage = null;

}

Sometimes it takes 2 minutes just to save the file, other times under 1 minute.
I ran this method 10 times, and each time i have, at some point, jumps in memory use.

The file used is here:

The docker file doesn’t really matter here, i just run the console app directly in docker
If needed, the google drive has it

Thank you, and hope this makes it more clear

@IBurzoEvoRWS thank you for the additional details. We will make investigation and then text you back. New details were added to the current opened task.
Please note, processing of graphics requires RAM, CPU and GPU resources. Photoshop has GPU optimization and uses 2GB Ram for this file, but to make Aspose.PSD available on any platforms and without any hardware dependencies, we can’t use any low-level GPU optimization. At this moment we work on optimization of RAM usage and processing time, your example will help us to make optimization more focused.