This is a migrated thread and some comments may be shown as answers.

Memory not getting released after creating a large mail merge

1 Answer 109 Views
RichTextEditor
This is a migrated thread and some comments may be shown as answers.
Pavel
Top achievements
Rank 1
Pavel asked on 25 Jan 2017, 05:15 PM

I am running into a memory issue when trying to perform a mail merge. I need to do two things:
1. Generate individual PDF files to be stored on a file share
2. generate a single PDF so it could be sent to a printer as a single job.

I am noticing, that after my large PDF file is generated, the memory usage remains very large. When I re-run the process, it starts climbing up, but then falls back down to an acceptable level during the generation of single document, only to climb back up during the final single PDF. I am pasting my code below. For some odd reason my random data isn't actually making it into the files, but since that's not my problem at this moment, I am not concerned about it.

using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Telerik.WinForms.Documents.FormatProviders.OpenXml.Docx;
using Telerik.WinForms.Documents.FormatProviders.Pdf;
using Telerik.WinForms.Documents.Model;
 
namespace MailMergeMemoryBenchmark
{
    public partial class RadForm1 : Telerik.WinControls.UI.RadForm
    {
        List<DummyItem> dataSource;
        public RadForm1()
        {
            //get the rest of the string at http://pastebin.com/i6PZiJ1c
            byte[] template = Convert.FromBase64String(@"UEsDBBQ...[TRUNCATED]");
            dataSource = new List<DummyItem>();
            for (int i = 0; i < 1000; i++)
            {
                dataSource.Add(DummyItem.GetRandom());
            }
            InitializeComponent();
            var provider = new DocxFormatProvider();
            radRichTextEditor1.Document = provider.Import(template);
            radRichTextEditor1.ScaleFactor = new Telerik.WinForms.Documents.Model.SizeF(.4f, .4f);
            radRichTextEditor1.ChangeAllFieldsDisplayMode(FieldDisplayMode.Code);
            radRichTextEditor1.Document.ShowMergeFieldsHighlight = true;
            radRichTextEditor1.Document.MailMergeDataSource.ItemsSource = dataSource;
        }
 
        private async void btnPerformMailMerge_Click(object sender, EventArgs e)
        {
            btnPerformMailMerge.Enabled = false;
            var progress = new Progress<string>(value => UpdateProgress(value));
            await Go(progress);
            btnPerformMailMerge.Enabled = true;
        }
 
        private void UpdateProgress(string value)
        {
            radLabel1.Text = value + Environment.NewLine;
        }
 
        private Task<bool> Go(IProgress<string> progress)
        {
            return Task.Run(() =>
            {
                var pdfProvider = new PdfFormatProvider();
 
                PdfExportSettings pdfExportSettings = new PdfExportSettings()
                {
                    ContentsCompressionMode = PdfContentsCompressionMode.Automatic,
                    ContentsDeflaterCompressionLevel = 9,
                    FloatingUIContainersExportMode = PdfInlineUIContainersExportMode.Image,
                    ImagesCompressionMode = PdfImagesCompressionMode.Automatic,
                    ImagesDeflaterCompressionLevel = 9,
                    InlineUIContainersExportMode = PdfInlineUIContainersExportMode.Image,
                };
                pdfProvider.ExportSettings = pdfExportSettings;
                byte[] letterBytes;
                radRichTextEditor1.Document.MailMergeDataSource.MoveToFirst();
                int i = 0;
                do
                {
                    using (var document = radRichTextEditor1.Document.MailMergeCurrentRecord())
                    {
                        letterBytes = pdfProvider.Export(document);
                        File.WriteAllBytes($"{i}-{DateTime.Now.Ticks}.pdf", letterBytes);
                    }
                    letterBytes = null;
                    progress.Report($"Merged {i + 1} out of {dataSource.Count()}");
                    i++;
                } while (radRichTextEditor1.Document.MailMergeDataSource.MoveToNext());
                progress.Report($"Starting large PDF creation");
                using (var document = radRichTextEditor1.MailMerge(true))
                {
                    letterBytes = pdfProvider.Export(document);
                    File.WriteAllBytes($"ALL RECORDS-{DateTime.Now.Ticks}.pdf", letterBytes);
                }
                progress.Report($"Done with large PDF creation");
                letterBytes = null;
                pdfProvider = null;
                pdfExportSettings = null;
                GC.Collect();
                return true;
            });
        }
 
 
    }
 
    internal class DummyItem
    {
        public string ContactName;
        public string CompanyName;
        public string Address;
        public static DummyItem GetRandom()
        {
            return new DummyItem()
            {
                ContactName = RandomStringGenerator.RandomString(20, 40),
                CompanyName = RandomStringGenerator.RandomString(20, 40),
                Address = RandomStringGenerator.RandomString(100, 200)
            };
        }
    }
 
    internal static class RandomStringGenerator
    {
        private const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 ";
        private static Random random = new Random();
        public static string RandomString(int minLength, int maxLength)
        {
            var length = random.Next(minLength, maxLength);
            return new string(Enumerable.Repeat(chars, length)
              .Select(s => s[random.Next(s.Length)]).ToArray());
        }
    }
}

1 Answer, 1 is accepted

Sort by
0
Hristo
Telerik team
answered on 26 Jan 2017, 03:25 PM
Hi Pavel,

Thank you for writing. 

I performed memory profiling of the described scenario and according to the provided code snippet and we could not isolate an issue with the consumed memory. Please check the attached screenshot and video showing the result on my end.

As it is seen, the memory consumption goes up and down while creating the mail merge and the pdf files. A considerable increase is observed while generating the large pdf file at the end. Once the job finishes and you force the Garbage Collector the memory is released.

Please also note that disposing of an object will not automatically release the memory it has consumed. The garbage collector is indeterministic in its nature and one cannot know when exactly it will release all objects marked as . You can also check the following articles:
I hope this information is useful. Should you have further questions please do not hesitate to write back.

Regards,
Hristo
Telerik by Progress
Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Tags
RichTextEditor
Asked by
Pavel
Top achievements
Rank 1
Answers by
Hristo
Telerik team
Share this question
or