Large aggregate reports crash chrome-pdf: chunk + parallel render + merge works for flat lists but breaks group subtotals and grand totals. What's the recommended pattern?



  • Hi jsreport team,

    We use jsreport to render operational reports for a records-management system, and large
    reports regularly crash or time out. We built a chunk-and-parallelize workaround that works
    well for flat list reports, but it doesn't work for aggregate reports (grouped reports with
    subtotals, summary/statistics reports, cross-tabs). Those still go to jsreport as a single
    huge render and fail. We'd like to know the recommended architecture for this case.

    Environment

    • jsreport 4.11.0, Node.js [version], Windows Server [version], hosted under IIS / iisnode

    • Server: 8 GB RAM, 2 CPU cores

    • Client: .NET 10 API using the jsreport.Client NuGet package

    • Recipe: chrome-pdf, engine: handlebars (plus pdfOperations merge of a header template)

    • Config (relevant part):

      {
      "templatingEngines": { "timeout": 1200000 },
      "chrome": { "timeout": 1200000 },
      "reportTimeout": 1200000,
      "workers": { "numberOfWorkers": 6 },
      "extensions": {
      "scripts": { "timeout": 1200000 },
      "express": { "inputRequestLimit": "200mb", "renderTimeout": 1200000 }
      }
      }

    What fails

    Our current workaround (works for flat lists)

    A SQL stored procedure returns the whole dataset as a JSON array. The .NET API then:

    1. Splits the array into chunks of rowsPerPage * pagesPerChunk rows
    2. Sends every chunk to jsreport in parallel as separate render requests
    3. Adds paging metadata to each chunk so the template knows where it is:
    4. Merges the returned PDFs in .NET (PdfSharp) and stamps "Page X of Y" after the merge

    This is fast and stable for flat roster or list reports.

    Why it doesn't work for aggregate reports

    • Group boundaries: chunks are cut by row count, so one group can be split across two chunks.
      The group header repeats and each half prints its own partial subtotal.
    • Aggregates are per chunk: subtotals, counts and sums that are computed in Handlebars
      helpers or in the template only see their own chunk's rows. {{Data.length}}-style totals
      repeat in every chunk. This matches what was described in topic 1451 ("Report generation
      takes too much time"), which ended without a solution.
    • Summary/statistics reports (counts by category x category, percentages of total) need
      the full dataset to produce even one page, so we can't split them at all. They go as one
      request with the whole JSON, and that is the request that crashes.

    Questions

    1. What is the recommended way to render large grouped / summary / aggregate reports in
      jsreport 4.x when the full dataset is too big for a single render, but the aggregates need
      all of the data?
    2. When a report is split into multiple renders and then merged, how should group subtotals
      and grand totals that span chunks
      be handled?
    3. How should memory and workers be sized for occasional very large renders (worker count,
      per-worker limits, Chrome strategy vs. server RAM)?
    4. When a client sends many render requests at the same time, how does jsreport handle them
      beyond numberOfWorkers, and should the client limit how many it sends at once?
    5. Are there template, recipe or layout practices you recommend for very long (2,000+ page)
      tabular PDFs with grouping and totals?

    Related threads: topic 1451 (totals repeating across parallel chunks), topic 492
    (reporting with a lot of data).

    Thanks for any guidance!



  • Chrome has real limits with very long tables — we can't remove them entirely, but we can push them out quite a bit.

    It turns out one of the things Chrome hits first is accessibility tagging. Tagging a table with tens of thousands of cells blows up both the file size and Chrome's printing itself. This can be turned off, and I've pushed a tagged option to master; it will be in the next release.

    You can already test it without upgrading — just add the following to the template

    <script>     
        window.JSREPORT_CHROME_PDF_OPTIONS = {
            tagged: false
        }
    </script>
    

    In our tests this took the same report from failing at ~1100 pages to rendering ~1300 pages, with the output roughly 30x smaller. Please try this first, it may be all you need.

    On your summary/cross-tab reports: those shouldn't be affected by this limit at all. Chrome's problem is the number of pages, not the number of input rows — a report consuming 200k rows and printing 2 pages renders in well under a second here. If one of those crashes, it's a different issue and worth a separate thread with the error.

    One more thing to check: numberOfWorkers: 6 on 2 cores and 8GB is quite high. Each worker can hold its own Chrome plus your dataset, so that alone could explain the container crash. I'd try 2.

    If you still need chunking for the really long ones, it doesn't have to break your totals — the trick is to compute aggregates once over the full dataset before rendering, split on group boundaries rather than row counts, and pass the precomputed subtotals and grand total into every chunk. Happy to go through it on a minimal demo if you can prepare one.


Log in to reply
 

Looks like your connection to jsreport forum was lost, please wait while we try to reconnect.