Aspose.Pdf x32 .NET out-of-memory when adding large images

We are running into out-of-memory (OOM) exceptions when we load multiple large (8 MB+) images into Aspose.Pdf documents in our x32 .NET application. As in the code below, we create intermediate Aspose Documents that each include a single image and combine the documents into a destination document. Based on our production application, PDF creation succeeds for a number of documents and it fails indefinitely once an out-of-memory exception occurs. The code below closely mirrors our actual application. OOM exceptions can be readily reproduced by running the test code with >10 iterations and >8 MB image files. As in our production application, the test application is unsalvageable after an OOM exception occurs. In the test app, selecting to continue after an OOM exception occurs, is immediately followed by another OOM exception - the memory is not being cleared. The test application performs without issue when compiled x64, but that is not an option for us. In your Java implementation it appears that there’s a MemoryCleaner class. Does a similar class exist in Aspose .NET? Is there another method or technique that you recommend for clearing the memory after each iteration so that our application does not degenerate until it fails?

Thanks in advance for any help.

Test app:

using Aspose.Pdf;
using System;
using System.Collections.Generic;
using System.IO;

namespace TestAspose
{
    // Command line example:
    // "C:\\Temp\\rome17MB.JPG"  20
    class Program
    {
        static void Main(string[] args)
        {
            License license = new License();
            license.SetLicense("Aspose.Pdf.lic");

            int totalBeforeFailure = 0;
            while (true)
            {
                Document destinationDocument = new Document();
                int nImages = 0;
                string imagePath = string.Empty;
                if (args.Length != 2)
                {
                    Console.WriteLine("Number of input arguments must be 2. Path to image and number of images.");
                }
                else
                {
                    imagePath = args[0];
                    nImages = Convert.ToInt32(args[1]);
                    Console.WriteLine($"Path = {imagePath}. Count = {nImages}");
                }

                List<ByteAndDocument> imageList = null;
                int index = 0;

                try
                {

                    imageList = new List<ByteAndDocument>();
                    for (; index < nImages; index++)
                    {
                        var byteAndStream = new ByteAndDocument();
                        System.Drawing.Image img = System.Drawing.Image.FromFile(imagePath);
                        using (MemoryStream memoryStream = new MemoryStream())
                        {
                            byteAndStream.Bytes = File.ReadAllBytes(imagePath);
                            Console.WriteLine($"Added file {index + 1} to byte array");
                        }
                        imageList.Add(byteAndStream);
                    }

                    // Create Aspose documents for each image
                    index = 0;
                    foreach (var image in imageList)
                    {
                        ByteToDocument(image);
                        index++;
                        Console.WriteLine($"Added byte array {index} to Aspose document");
                    }

                    // Add each image to the destination document
                    index = 0;
                    foreach (var image in imageList)
                    {
                        destinationDocument.Pages.Add(image.Document.Pages);
                        index++;
                        totalBeforeFailure++;
                        Console.WriteLine($"Adding sub (image) Aspose document {index} to destination document");
                    }

                    Console.WriteLine($"Finished creating {index} image->Aspose document conversions for this iteration. {totalBeforeFailure} total successful image->Aspose document conversions!\n\n");
                }
                catch (Exception e)
                {
                    Console.WriteLine($"Total number of successful image->Aspose document conversions before failure {totalBeforeFailure}. Exception: {e}");
                    totalBeforeFailure = 0;

                    Console.WriteLine("\nContinue (y/n)?: ");
                    var key = Console.ReadKey();
                    if (key.KeyChar.ToString().ToUpper() == "N")
                    {
                        break;
                    }
                }
                finally
                {
                    foreach (var img in imageList)
                    {
                        if (img.Document != null)
                        {
                            img.Document.Dispose();
                            img.Document = null;
                        }
                        img.Bytes = null;
                    }
                    imageList.Clear();
                    imageList = null;

                    destinationDocument.Dispose();
                    destinationDocument = null;
                }
            }
        }

        private static void ByteToDocument(ByteAndDocument byteAndStream)
        {
            byteAndStream.Document = new Document();
            byteAndStream.Document.Pages.Add();
            Page page = byteAndStream.Document.Pages[1];
            MemoryStream memoryStream = new MemoryStream(byteAndStream.Bytes);

            page.Resources.Images.Add(memoryStream);
        }

        public class ByteAndDocument
        {
            public byte[] Bytes { get; set; }
            public Document Document { get; set; }

            public ByteAndDocument()
            {
                Bytes = null;
                Document = null;
            }
        }
    }
}

@jdmulkey

Thank you for contacting support.

Would you please share sample image file by uploading it to Google Drive, Dropbox etc so that we may investigate further to help you out.

I used the satellite image of Rome located at this link: http://www.effigis.com/wp-content/uploads/2015/02/DigitalGlobe_WorldView2_50cm_8bit_Pansharpened_RGB_DRA_Rome_Italy_2009DEC10_8bits_sub_r_1.jpg

It’s around 17 MB. I used 10 iterations with the test (console) app above with this image. As noted, the first few iterations of the loop work, but eventually an OOM exception occurs that forces the app to be restarted to make the app work again - in x32.

Thanks for looking into it.

@jdmulkey

Thank you for sharing requested data.

We have logged a ticket with ID PDFNET-45516 in our issue management system for further investigations. The ticket ID has been linked with this thread so that you will receive notification as soon as the ticket is resolved.

We are sorry for the inconvenience.