This article is intended to provide a general overview of what kind of performance you can expect from the MailMerge class in various typical situations. This document can be used as a starting point for evaluating your own performance tests.

Test Environment

To perform these tests, we used a midrange PC with an AMD Ryzen 7 2700X eight-core 3.70 GHz processor (comparable to Azure D-Series VMs) and 16GB of memory.

The test application is a .NET Core Console App using the classes MailMerge TX Text Control .NET Server for ASP.NET
DocumentServer Namespace
MailMerge Class
The MailMerge class is a .NET component that can be used to effortlessly merge template documents with database content in .NET projects, such as ASP.NET web applications, web services or Windows services.
and ServerTextControl TX Text Control .NET Server for ASP.NET
TXTextControl Namespace
ServerTextControl Class
The ServerTextControl class implements a component that provide high-level text processing features for server-based applications.
from TX Text Control .NET Server for ASP.NET 31.0 SP2.

MailMerge Template

As a template, we used a simple but typical invoice template with a header and SVG logo, some static data, an address merge field block, and a repeating block that lists the invoice line items.

MailMerge Performance

As a data source, the following C# object is used with different number of line items and invoices resulting in different number of pages from 1 page to hundreds of generated pages.

public class Invoice {
public Buyer Buyer { get; set; }
public List<LineItem> LineItems { get; set; }
public float Total {
get {
var total = 0F;
foreach (var item in LineItems) {
total += item.LineTotal;
}
return total;
}
}
}
public class LineItem {
public string ProductID { get; set; }
public string Name { get; set; }
public int Quantity { get; set; }
public float Price { get; set; }
public float LineTotal {
get { return Price * Quantity; }
}
}
public class Buyer {
public string Name { get; set; }
public string ContactName { get; set; }
public string Street { get; set; }
public string City { get; set; }
}
view raw test.cs hosted with ❤ by GitHub

The following code shows the basic merge process, including the export to PDF.

using (TXTextControl.ServerTextControl tx = new TXTextControl.ServerTextControl()) {
tx.Create();
tx.Load("invoice-template.tx", TXTextControl.StreamType.InternalUnicodeFormat);
using (MailMerge mailMerge = new MailMerge()) {
mailMerge.TextComponent = tx;
mailMerge.MergeObjects(invoices, false);
}
tx.Save("results.pdf", TXTextControl.StreamType.AdobePDF);
}
view raw test.cs hosted with ❤ by GitHub

The invoices data object is an object of type List<Invoice> that is generated prior to the benchmark merge process. Each Invoice is represented as a Document in the following diagrams.

The following screenshot shows the resulting document of scenario 1, where 1 invoice with 5 block data rows is created.

MailMerge Performance

Test Scenarios

All test scenarios are executed across different test loads using the same test environment.

Scenario 1: Small Documents

This scenario shows the performance of simple templates with 5 line items (merge block rows):

  • One page template
  • 1 merge block with 5 data rows
  • Number of pages per invoice: 1
  • Variable: Number of documents (invoices)

Duration for a single document: 0.35 seconds

MailMerge Performance

As you can see in the chart above, a single document is generated in less than 0.35 seconds and increases linearly. 80 documents are generated in about 16 seconds.

Scenario 2: Typical Documents

This scenario shows the performance of simple templates with 100 line items (merge block rows):

  • One page template
  • 1 merge block with 100 data rows
  • Number of pages per invoice: 6
  • Variable: Number of documents (invoices)

Duration for a single document: 3.2 seconds

MailMerge Performance

As you can see in the chart above, a single document with 100 merge blocks rows is generated in 3.2 seconds and increases linearly. In the last run, the resulting document contains generated 480 pages with 80000 merge block rows.

Scenario 3: Increasing Merge Block Rows

This scenario shows the performance of simple templates with an increasing number of merge block rows:

  • One page template
  • 1 merge block
  • Number of pages per invoice: Variable
  • Number of invoices: 1
  • Variable: Number of data rows

MailMerge Performance

As visualized in the chart above, a single document with 1 merge blocks row is generated in 0.23 seconds and increases exponentially. In the last run, the resulting document contains generated 59 pages with 1280 merge block rows.

Scenario 4: Two Merge Blocks

This scenario shows the performance of simple templates with an increasing number of merge block rows for 2 merge blocks:

  • One page template
  • 2 merge blocks
  • Number of pages per invoice: Variable
  • Number of invoices: 1
  • Variable: Number of data rows

MailMerge Performance

As visualized in the chart above, a single document with 1 merge blocks row is generated in 0.34 seconds and increases exponentially. In the last run, the resulting document contains generated 8 pages with 160 merge block rows in two merge blocks.

What can be observed is that the same number of merge block rows divided into 2 merge blocks is faster than a single table.

Scenario 5: SaveSettings PDF Features

This scenario shows the performance of typical PDF features such as encryption, digital signatures and embedded files.

  • One page template
  • 1 merge block with 10 rows
  • Number of pages per invoice: 1
  • Number of invoices: 5
  • Variable: Different SaveSettings features

The following features are used for this test:

  • Encryption: The document is encrypted with a user and master password.
  • Embedded Files: A typical XML (ZUGFeRD) is embedded in the PDF document.
  • Digital Signature: The entire document is encrypted and signed with a PFX certificate.
  • SignatureField: A single signature field is replaced with a signature image (SVG) and signed with a PFX certificate.

MailMerge Performance

It can be observed that additional features such as encryption doesn't take significant more time to process. The test Embedded Files depends on the size of the to be embedded document.

Scenario 6: Formulas vs. Static Data

This scenario illustrates the differences between calculating dynamic values based on formulas in a merge block and merging static data from a data source.

MailMerge Performance

  • One page template
  • 1 merge block
  • 2 formulas (line total and total sum)
  • Number of invoices: 1
  • Variable: Merge block rows

MailMerge Performance

The results show that the use of formulas is acceptable in shorter tables (low number of merge rows). The more rows are used, the more often formulas are calculated.

Conclusion

These benchmarks show the performance of the MailMerge class in a single-threaded merge process. If you plan to use the MailMerge class in a high-performance environment where documents are created in parallel (such as in a Web API), a multi-process approach is recommended.

Learn More

This article shows how to generate documents concurrently by creating multiple, truly parallel processes.

True Parallel Processing of Documents using MailMerge