Reporting - Document Generation Performance Improvements (v18.1)

Reporting Team Blog
03 May 2018

For a long while now, we have been on a mission to improve performance and memory handling when creating very large reports. Traditionally, we kept a complete document model in memory in order to print the document, or export to any of the supported formats. As a result, some customers ran into trouble when they created documents with thousands of pages, and in our release v17.2 we took a first huge step to solve these problems by introducing the PdfStreamingExporter tool. This tool exports reports to PDF in streaming and multi-threaded streaming modes, which reduces memory consumption in comparison to the standard in-memory mode. For the upcoming release v18.1, we have managed to implement a further significant improvement.

The CachedReportSource component

The new component CachedReportSource stores document pages in the file system or in a database during document generation. This decreases memory consumption when creating very large documents — in fact, with the new component, the size of a document is limited largely by the available storage space, with memory consumption increasing only slowly with very large page numbers.

The CachedReportSource component manages caching logic and acts as a mediator between a report and a Document Viewer. When a Document Viewer is bound to a report, the associated CachedReportSource generates the report document and stores it in the configured storage. The Document Viewer loads only visible document pages into memory and disposes pages when they are rendered invisible by scrolling.

Note that you can also benefit from the new functionality if your goal is to export a report, even more so if you target several output formats. An export code sample is shown below.

Design Time (WinForms Apps)

You can utilize the CachedReportSource component at design time in Windows Forms applications. Check the Cache Document Source option in the Document Viewer’s smart tag menu after setting the Document Source property:

WinForms Design Time Cached Document Source

A CachedReportSource component is automatically added to the form. You can now configure component settings, most importantly to choose one of the ready-to-use document storage options provided by the CachedReportSource.Storage property:

  • MemoryDocumentStorage - Use in-memory storage, but with a more compact document model than the standard, non-cached model

  • FileDocumentStorage - Store a set of files in a a specified directory

  • DbDocumentStorage - Store the document model in any database supported by our XPO ORM

Storage settings

Runtime use cases

A runtime setup approach is supported on all platforms. Here is an example for WPF, where the FileDocumentStorage uses a folder in the user profile:

using DevExpress.XtraPrinting.Caching;
using System.IO;

...

var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var path = Path.Combine(appDataPath, "MyApplicationFolder");
var storage = new FileDocumentStorage(path);
var report = new MyReport();
var cachedReportSource = new CachedReportSource(report, storage);

documentPreviewControl.DocumentSource = cachedReportSource;
cachedReportSource.CreateDocumentAsync();

The method CreateDocumentAsync runs document generation asynchronously in a background task. Alternatively, you can use CreateDocument to generate a large document synchronously, and then export it by calling methods exposed by the PrintingSystem associated with the CachedReportSource:

cachedReportSource.CreateDocument();
cachedReportSource.PrintingSystem.ExportToPdf("MyPdfDocument.pdf");

For Web applications, we supply the component CachedReportSourceWeb. Here’s how to use it in ASP.NET WebForms:

using DevExpress.XtraReports.Web;
using DevExpress.XtraPrinting.Caching;
using System.IO;

...

protected void Page_Load(object sender, EventArgs e) {
  var appDataPath = HttpRuntime.CodegenDir;
  var path = Path.Combine(appDataPath, "tempDocumentsFolder");
  var storage = new FileDocumentStorage(path);
  var report = new XtraReport1();
  var cachedReportSource = new CachedReportSourceWeb(report, storage);

  ASPxWebDocumentViewer1.OpenReport(cachedReportSource);
}

For ASP.NET MVC, here is a sample View:

@model DevExpress.XtraReports.Web.CachedReportSourceWeb

@Html.DevExpress().WebDocumentViewer(settings => {
  settings.Name = "WebDocumentViewer1";
}).Bind(Model).GetHtml()

… and the corresponding controller:

using DevExpress.XtraPrinting.Caching;
using DevExpress.XtraReports.Web.WebDocumentViewer.Native;
using System.IO;

...

public class HomeController : Controller {
  public ActionResult Viewer() {
    var appDataPath = HttpRuntime.CodegenDir;
    var path = Path.Combine(appDataPath, "tempDocumentsFolder");
    var storage = new FileDocumentStorage(path);
    var report = new XtraReport1();
    var cachedReportSource = new CachedReportSourceWeb(report, storage);

    return View(cachedReportSource);
  }
}

Performance comparison results

We used our updated report demo Large Quantity of Data to measure memory consumption in various scenarios. Here are the results (values in Mbytes):

Number of Pages In Memory creation Memory Storage File Storage
DB Storage
Pdf Export from DB Storage

RAM RAM RAM HDD RAM HDD RAM
5000 294 134.4 95 32 84 28 155
10000 N/A 250 140 54 145 56 368
50000 N/A N/A 191 270 204 282 713
100000 N/A N/A 245 544 268 558 1,160

Try it!

The beta release of v18.1 is available to active Universal subscribers now. Please give the new features a try, and get back to us with any feedback! We are very interested to hear how CachedReportSource improves your reporting scenarios.

Free DevExpress Products - Get Your Copy Today

The following free DevExpress product offers remain available. Should you have any questions about the free offers below, please submit a ticket via the DevExpress Support Center at your convenience. We'll be happy to follow-up.
No Comments

Please login or register to post comments.