RDLC Report and Performance in Microsoft Dynamics NAV 2015 and 2016


In a previous Blog dated back year 2014

https://blogs.msdn.microsoft.com/nav/2014/03/09/rdlc-report-and-performance-in-microsoft-dynamics-nav/

I have tried to give an overview related to the Out Of Memory exception that you might hit with Microsoft Dynamics NAV RDLC Report with the following versions: 2009 R2, 2013 and 2013 R2.

The main focus of my dissertation now is based on the improvement made with Microsoft Dynamics NAV 2015 and 2016 related to report performance. I would encourage you to post your comments and thoughts, as usual. Have a good read.

 

NAV 2015  (RDLC 2010 – Report Viewer 2014)

The same optimization tips posted in the previous blog are still valid. With Microsoft Dynamics NAV 2015 it has been introduced out-of-the-box a powerful feature to automatic schedule reports to be printed server side through a Job Queue. You could take as reference the MSDN entry below

https://msdn.microsoft.com/en-us/library/dn757302(v=nav.80).aspx

And the following video

http://community.dynamics.com/nav/b/navvideos/archive/2015/02/02/how-do-i-schedule-report-execution-in-microsoft-dynamics-nav-2015

Please, be sure to have enough memory server side to cope with the Schedule a Report feature.

With Microsoft Dynamics NAV 2015 and considering so-called heavy reports, I would then strongly recommend you to enable and take advantage of this feature. The same principle applies if you have to print a discrete amount of reports (typically from hundreds to thousands) in a short time frame.

 

NAV 2016  (RDLC 2010 – Report Viewer 2015)

With this latest version, the Microsoft Dynamics NAV Windows client is available in a 32-bit version and 64-bit version. The 32-bit version of the Microsoft Dynamics NAV Windows client can be run on either a 32-bit or 64-bit version of a Windows operating system. The 64-bit version of the Microsoft Dynamics NAV Windows client can only be run on a 64-bit version of a Windows operating system. On a 64-bit Windows operating system, the 64-bit version of the Microsoft Dynamics NAV Windows client is used by default.

If you are using the 64-bit Microsoft Dynamics NAV Windows Client this now enables the usage of more memory for report dataset therefore the Out Of Memory bar is raised higher compared to all other versions. Even if the Microsoft Dynamics NAV 2016 64-bit Windows Client might allow you to preview / print a more consistent dataset compared to all previous versions that do support RDLC reports, it is always recommended for long batch printing (heavy reports) to enable the schedule a report feature in order to have a more robust server side printing in background.

 

Important considerations using Server Side Printing

Microsoft Dynamics NAV RDLC Report memory usage and performance are tightly related.

Considering the same dataset dimension, memory footprint and performance are influenced by:

  • VB.NET SHARED VARIABLES  Within Microsoft Dynamics NAV Report context, these are typically used for SETDATA and GETDATA trick. E.g. in Microsoft Dynamics NAV 2016 standard Cronus W1 Report 206 you could find these shared variables in the RDLC Report Code section

 

Shared Data1 as Object

Shared Data2 as Object

Shared Data3 as Object

Shared Data4 as Object

Etc.

Even if several (many) standard reports are using VB.NET Shared Variables, this is basically discouraged within RDLC reports since the Report Viewer cannot reuse the expressionhost and therefore creates a new one each time the report is run. The recycle of these objects is pretty crucial in some scenarios and is tightly depending on legacy Code Access Security (CAS) policy switch.

  • CODE ACCESS SECURITY (CAS) POLICY SWITCH. The default value for Microsoft Dynamics NAV 2015 e NAV 2016 is true (CAS Policy enabled). CAS policy is defined server side by the NetFx40_LegacySecurityPolicy parameter that you will find in the Microsoft.Dynamics.NAV.Server.exe.config XML file in the NAV Server folder.

 

Stated the above, to demonstrate the behavior and results, I am using a simple codeunit to be run server side through Job Queue.

OnRun()

FOR i := 1 TO 16000 DO BEGIN

SaveReportAsPdf(i);

END;

LOCAL SaveReportAsPdf(loopNo : Integer)

report.USEREQUESTPAGE := FALSE;

rec.FINDFIRST;

rec.SETFILTER(“No.”, rec.”No.”);

report.SETTABLEVIEW(rec);

report.SAVEASPDF(‘C:/Temp/PDF/’ + FORMAT(loopNo) + ‘report-to-delete.pdf’);

CLEAR(report);

 

With Local variables for function SaveReportAsPdf

Name  DataType        Subtype          Length

report Report Sales – Invoice

rec       Record Sales Invoice Header

(NOTE: report variable could be either Report ID 206 or Report ID 1306, depending on the test performed below.)

 

This codeunit is generating 16.000 PDF document server side and for the sake of the test I run this 4 time using report 206 (that contains VB.Net shared variables) and report 1306 (does not contain any VB.Net shared variable), with or without CAS policy enabled.

See below results of the test

NETFX40 SWITCH Shared Variables No. doc MEM (GB) Time (min)
TRUE YES
500 0,4 3
1000 0,6 6
2000 1,1 13
3000 1,5 21
4000 2 29
8000 3,7 65
12000 5,5 102
16000 7,3 152
FALSE YES 500 3 5
1000 3,8 11
2000 4,2 23
3000 4,3 35
4000 4,5 47
8000 4,4 94
12000 4,7 144
16000 4,8 193
TRUE NO 2000 0,2 4
4000 0,2 7
8000 0,2 13
12000 0,2 19
16000 0,2 25
FALSE NO 2000 7 5
4000 7,3 12
8000 8,1 27
12000 6,6 45
16000 6,9 65

 

  • CAS policy enabled and with VB.Net shared variables (Report 206)

Memory behavior: slowly but constant consumption increase without appropriate recycling. This scenario cause memory leak. Faster execution than with CAS Policy disabled (152 mins for 16000 documents). This is the typical NAV default Scenario.

 

  • CAS policy disabled and with VB.Net shared variables (Report 206)

Memory behavior: initially increase consumption very fast until it starts recycling. With the appropriate memory size, it does not cause memory leak. This scenario has the slowest execution (193 mins for 16000 documents).

 

  • CAS policy enabled and without VB.Net shared variables (Report 1306)

Memory behavior: very low and stable consumption around 200 MB. Memory is completely released for every document printed. It does not cause memory leak. This is the best scenario both in terms of memory footprint and performance: it takes up to 20 mins to generate 16000 PDF documents.

 

  • CAS policy disabled and without VB.Net shared variables (Report 1306)

Memory behavior: initially increase consumption very fast until it starts recycling. With the appropriate memory size, it does not cause memory leak. Really very slow performance compared to the same scenario with CAS Policy enabled

 

Takeaways from this practical test could be resumed as per the following:

  1. Avoid using VB.Net shared variables as much as possible within RDLC Reports
  2. If you cannot make it to get rid of these and your requirement is to generate a high volume of reports in short time, it is recommended to deploy a dedicated NAV Server service with CAS policy disabled in order to avoid memory leak, even if this might result in a slower execution.

 

These postings are provided “AS IS” with no warranties and confer no rights. You assume all risk for your use.

Duilio Tacconi (dtacconi)

Microsoft Dynamics Italy

Microsoft Customer Service and Support (CSS) EMEA

A special thanks to Christian Clausen / Telebilling

Comments (5)

  1. Claus Lundstrøm says:

    Really what Microsoft should do is to only create one dataset per document and not place all documents in one huge dataset, then we could completely eliminate SETDATA and GETDATA, and have great performing reports.
    You guys have done it for Word Reports, so should be easy to do for RDLC reports as well.
    And it would also dramatically increase the speed for us designing reports, since we did not have to worry about SETDATA and GETDATA at all.

    /Claus Lundstrøm, MVP

    1. Hello Duilio,

      please tell me, what is the Problem to do this what Claus have suggested?

      Yours

      Michael

    2. Klemmensen says:

      Totally agree here with Claus. I would actually like to go one step further and say the dataset and the layout should never be stored in the same object description. A dataset can be reused for many different reports if designed with care and if we added things like where to send it (email, pdf, printer, …) or how many copies or other info the layout is now just the layout and will just follow the instructions in the dataset. We can partly already do that today as we can safe the dataset and run the layout on the same dataset again.

  2. Thanks for the comment, Claus / Michael. Actually I have once again sent your valuable suggestion internally. I would also dare to log your requests and concerns through MSCONNECT, if you haven’t done already. http://connect.microsoft.com/dynamicssuggestions
    Basically, refactoring e.g. report 206 to be more similar 1306 could be achieved but it needs to be analyzed in deep (e.g. how to redo copyloop in another way, etc.)

  3. RWendler says:

    Hi Duilio,

    your blog saved me today 🙂 We had a serious performance issue and we were able to solve this with enabling NetFx40_LegacySecurityPolicy again. We deactivate this parameter, because we are using are product, which forced us to do that.

    Unfortunately this cause a huge difference on our reports:
    20 pages – with parameter – 2-4 seconds
    20 pages – withour parameter – more than 1 minute