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:
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 modelFileDocumentStorage
- Store a set of files in a a specified directoryDbDocumentStorage
- Store the document model in any database supported by our XPO ORM
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.