Generating a report with a lot of data taking longer than expected
-
I am running a local jsreport server and I'm passing my report json that is about 53.5 mb in size. I'm using a chrome-pdf recipe. My problem is that it takes about ~9 minutes and 35 seconds to render this report.
Here is my HTML:
<!DOCTYPE html> <html> <head> <style> @media print { div, table, tr{ page-break-inside: avoid; } .row{ page-break-before:always; } .row:first-child{ page-break-before:avoid; } } body{ font-family: Arial; } table, th, td { border-collapse: collapse; } td, th{ border-bottom:1px solid black; border-left:1px solid black; text-align:center; } table { width: 100%; table-layout: fixed; margin-bottom:2px; } td{ word-wrap: break-word; font-size:5pt; } td:first-child, th:first-child{ border-left:0px; } th{ font-size:5pt; } .title, .subtitle{ text-align: center; } .title{ font-size: 14pt; font-weight: bold; } .subtitle{ font-size: 10pt; } .container{ padding-left:20px; padding-right:20px; padding-bottom:20px; } .medicationTable{ border: 1px solid black; vertical-align:text-top; } .medicationData:first-child{ border-right:1px solid black; width:15%; } .medicationData{ text-align:left; font-size:6pt; vertical-align:text-top; } .administrationTable{ vertical-align:text-top; } .drugTitle{ font-size:8pt; font-weight:bold; } .orderSig{ font-size:7pt; font-weight:bold; } .row{ margin-top:20px; border-left:1px solid black; border-top:1px solid black; margin-bottom:5px; } .row:after { content: ""; display: table; clear: both; } .patientColumn{ font-size:6pt; border-right:1px solid black; box-sizing: border-box; padding:2px; text-align: left; vertical-align: top; font-weight:normal; } </style> </head> <body> <div class="title"> {{Title}} </div> <div class="subtitle"> {{#if Settings.RunDate}} {{#eq StartDate EndDate}} For: {{StartDate}}<br> {{else}} From: {{StartDate}} - {{EndDate}}<br> {{/eq}} {{/if}} {{#if Settings.GeneratedDate}} Generated: {{GeneratedDate}}<br> {{/if}} {{#if Settings.Facility}} Facility: {{Facility}}<br> {{/if}} {{#if Settings.Pass}} Pass: {{Pass}}<br> {{/if}} {{#if Settings.RunBy}} Run By: {{RunBy}}<br> {{/if}} </div> <div class="container"> {{#each Patients}} <table class="row"> <tr> <th class="patientColumn"> <b>Patient</b><br> Name: {{Name}}<br> {{#if ../Settings.Number}} Number: {{Number}}<br> {{/if}} {{#if ../Settings.DateOfBirth}} Date Of Birth: {{DateOfBirth}}<br> {{/if}} {{#if ../Settings.Location}} Location: {{Location}}<br> {{/if}} {{#if ../Settings.Gender}} Gender: {{Gender}}<br> {{/if}} {{#if ../Settings.Weight}} Weight: {{Weight}} {{/if}} </th> {{#if ../Settings.Allergies}} <th class="patientColumn"> <b>Allergies</b><br> {{#if Allergies}} {{#each Allergies}} {{Description}}<br> {{/each}} {{else}} There are no allergies for this patient {{/if}} </th> {{/if}} {{#if ../Settings.Diagnoses}} <th class="patientColumn"> <b>Diagnoses</b><br> {{#if Diagnoses}} {{#each Diagnoses}} {{Description}}<br> {{/each}} {{else}} There are no diagnoses for this patient {{/if}} </th> {{/if}} <th class="patientColumn"> <b>Nurse Signatures</b><br> {{NurseSignatures}} </th> {{#if ../Settings.PatientNotes}} <th class="patientColumn"> <b>Notes</b><br> {{#if Notes}} {{#each Notes}} {{Text}}<br> {{/each}} {{else}} There are no notes for this patient {{/if}} </th> {{/if}} </tr> </table> {{#each Orders}} <table class="medicationTable"> <td class="medicationData"> <span class="drugTitle">{{DrugName}}</span><br> {{#if ../../Settings.RxNum}} Rx Number: {{RxNumber}}<br> {{/if}} Dispense Type: {{DispenseType}}<br> {{#if ../../Settings.StartDate}} Start Date: {{StartDate}}<br> {{/if}} {{#if ../../Settings.StopDate}} Stop Date: {{ExpirationDate}}<br> {{/if}} {{#if ../../Settings.DcDate}} Discontinue Date: {{DCDate}}<br> {{/if}} {{#if ../../Settings.Prescriber}} Prescriber: {{Prescriber}}<br> {{/if}} Patient: {{Patient}}<br><br> {{#if ../../Settings.Sig}} <span class="orderSig">{{Sig}}</span> {{/if}} </td> <td class="medicationData"> {{#if Passes}} <table class="administrationTable"> <tr> <th>Time</th> <th>Event</th> {{#each ../../Days}} <th>{{this}}</th> {{/each}} </tr> {{#each Passes}} <tr> <td rowspan="{{RowSpan}}">{{Time}}</td> <td>Init.</td> {{#each Results}} {{#if Result}} <td style="{{Style}}">{{Result}}</td> {{else}} {{#if Scheduled}} <td style="{{Style}}">{{../../../../Settings.EmptyBoxText}}</td> {{else}} <td style="{{Style}}"></td> {{/if}} {{/if}} {{/each}} {{#each Procedures}} <tr> <td>{{Code}}</td> {{#each Results}} <td>{{Result}}</td> {{/each}} </tr> {{/each}} </tr> {{/each}} </table> {{else}} No scheduled give information to show. {{/if}} {{#if NonPassGives}} <div> <br><b>Non Scheduled Gives</b><br> {{#each NonPassGives}} Date: {{GiveDateTime}}, Nurse: {{NurseInitials}}, Quantity/Result: {{Quantity}}{{Result}}<br> {{/each}} </div> {{/if}} {{#if ../../Settings.OrderNotes}} {{#if Notes}} <div> <br><b>Notes</b> {{#each Notes}} <br>{{Date}} - {{Text}} {{/each}} </div> {{/if}} {{/if}} {{#if ../../Settings.DispenseTypeChanges}} {{#if DispenseTypeChanges}} <div> <br><b>Dispense Type Changes</b> {{#each DispenseTypeChanges}} <br>{{UserLastName}}, {{UserFirstName}} - From {{OldValue}} to {{NewValue}} on {{Date}} {{/each}} </div> {{/if}} {{/if}} </td> </table> {{/each}} {{/each}} </div> </body> </html>
I've found that when I comment out the
{{#each Results}}
loop on line 278, the report renders in ~4 minutes and 45 seconds. This loop would be looping through 31 results each time it gets hit.Any help in finding a way to speed this process up would be greatly appreciated.
-
I believe the rendering spends 99% of the time in chrome pdf conversion right? You can see it if you run the rendering in debug mode. Or in the output logs.
In this case, I would recommend removing the css styles and see the performance difference. There can be a particular style causing performance degradation and maybe you can work around it with a different style. As the second step, I would recommend to at least try/prototype the report without
table
elements. It seems to be poorly performing in my experience.You can also try to run the rendering on better HW of course.
Sometimes it is also possible to split a long report into multiple sections. Run the rendering in parallel and use pdf utils to append the sections into one pdf in the end.
However, this is not always possible and also quite complex to do. https://jsreport.net/learn/pdf-utils#usage-in-script
-
I tried removing the css styling and that did knock the render time down to ~5 minutes. Then I tried removing the
<table class="administrationTable">
table and replacing everything in there to use divs instead, however that only knocked the time down 30 more seconds. I do need the css styling however. So I suppose my best option is probably to look into the parallel rendering at this point?