cancel
Showing results for 
Search instead for 
Did you mean: 

Crystal Report 2013 memory problem

Former Member
0 Kudos

Hi,

I am developing a Windows service. The service calls Crystal Report to generate PDFs. When a new contract appears in database (MS Access), the service reads contract number and build a formular. Then pass the formular to ReportDocument. The code looks like this

using (ReportDocument report = new ReportDocument()) {

  report.Load("contract.rpt");

  // some initialize report

  foreach (var contract in contracts) {

    report.RecordSelectionFormula = BuildFormular(contract);

    report.ExportToDisk(ExportFormatType.PortableDocFormat, BuildOutputFilename(contract));

  }

  report.Close();

}

It works fine. When deploy on production, I want the location of Access file can be changed programmatically. So I modified the code

using (ReportDocument report = new ReportDocument()) {

  report.Load("contract.rpt");

  // some initialize report

  foreach (ReportDocument subreport in report.Subreports) {

     foreach (Table table in subreport.Database.Tables) {

       table.Location = MdbPath;

    }

  }

  foreach (Table table in report.Database.Tables) {

    table.Location = MdbPath;

  }

  foreach (var contract in contracts) {

    report.RecordSelectionFormula = BuildFormular(contract);

    report.VerifyDatabase();

    report.ExportToDisk(ExportFormatType.PortableDocFormat, BuildOutputFilename(contract));

  }

  report.Close();

}

It works but memory increases over time. Here are Private Bytes (I use Performance Monitor tool)

  • 10:45 - 58.000MB
  • 11:00 - 61.801MB
  • 11:15 - 64.611MB
  • 11:30 - 65.544MB
  • 11:45 - 65.716MB
  • 12:30 - 69.095MB

I also attached some screenshot of report of DebugDiag tool.

My environment:

  • Net framework 4.5
  • Tool runs as Windows Service
  • Crystal Report 2013 (Crystal Report Runtime 32bit 13.0.10.1385).
  • Database: MS Access/OleDb

Any suggestion?

Many thanks

Accepted Solutions (1)

Accepted Solutions (1)

former_member183750
Active Contributor
0 Kudos

Remove report.VerifyDatabase();


Not needed and only slows down the performance of the report engine.


Under report.Close();


add


report.Dispose;


You may want to see if adding GC.Collect will be of any use also.



- Ludek

Senior Support Engineer AGS Product Support, Global Support Center Canada

Follow us on Twitter

Former Member
0 Kudos

Hi Ludek,

I followed your advice. I removed VerifyDatabase(). Thanks. It make my program faster .

I added Dispose() right after Close(). Also added GC.Collect().

using (ReportDocument report = new ReportDocument()) {

  report.Load("contract.rpt");

  ...

  report.Close();

  report.Dispose();

}

GC.Collect();

GC.WaitForPendingFinalizers();

Memory still increases steadily. Is there any thing else to do?

former_member183750
Active Contributor
0 Kudos

Now it would be interesting to see if this is CR or something else in the app causing the memory to keep going up. Note that this is the 1st time I hear of this issue in this version and SP of CR. Nevertheless, I'm open to it being CR - perhaps in connection with Access as Access is really not sued that much anymore.

Anyhow, I'd like you to take one of the reports - with saved data and run it in a loop. Do you see the memory increasing? I'd assume not, so move to next test;

Use a report that has no saved data - do not change the path to the Access database and again, loop through the report. Do you see memory increasing in this case?

The obvious 3rd test would now be - same as above, but change the path to the Access database.

Note that none of the above tests involve a service or populating of selection formulas.

- Ludek

Former Member
0 Kudos

Hi Ludek,

I start a new console project with a simple report. I enclosed VS solution and memory statistic.

The code is quite simple. The report do nothing but display the formular. I ran it for 50 minutes, the memory increase from 37.426MB to 43.267MB (~ 6MB). Do I miss any thing?

class Program {

   static void Main(string[] args) {

        List<String> policies = new List<string>() {

            "00", "01", "02", "03", "04",

            "05", "06", "07", "08", "09"

        };

        while (true) {

            GenerateReportWithoutSubreport(policies);

            System.Threading.Thread.Sleep(1000);

        }

    }

    private static void GenerateReportWithoutSubreport(List<string> policies) {

       using (var report = new ReportDocument()) {

            report.Load("TestWithoutSubreport.rpt", OpenReportMethod.OpenReportByDefault);

            foreach (string policy in policies) {

                Console.WriteLine("Policy: " + policy);

                foreach (FormulaFieldDefinition formula in report.DataDefinition.FormulaFields) {

                    if (formula.Name == "criterion") {

                        formula.Text = policy;

                        break;

                    }

                }

                var outputFilename = policy + ".pdf";

                report.ExportToDisk(ExportFormatType.PortableDocFormat, outputFilename);

            }

            report.Close();

            report.Dispose();

        }

        GC.Collect();

        GC.WaitForPendingFinalizers();

    }

}



former_member183750
Active Contributor
0 Kudos

That was not quite the test I had in mind. I wanted a simple win app, looping through some x number of times and exporting the report.

E.g.;

For 1 to x           ' (set x to say 100)

Load report

Export report to PDF

close report

dispose report

next x

Do the above with saved data report, then no saved data, then no saved data and changing the db path.

I do not want any connection to your service. E.g.; I want this to be a pure win CR app for now. This is the only way you will prove to me that CR is leaking memory.

- Ludek

Former Member
0 Kudos

Hi Ludek,

I will make a windows form app as your comment. However, I will write C# program because I do not know VB.NET.

If you have time, please have a look at the docx file. It may tell something about my situation.

Thank you,

Vi

Former Member
0 Kudos

Hi Ludek,

I wrote 3 tests. You can get detail here:

Here are summary:

Tests are a Windows Form apps with one main form which has one button. If we click on the button, it call Crystal Report to generate 100 pdf. The Access database is simple - one table which has 10 records.

Test case 1 - Saved data report.

I clicked 7 times (700 pdf created). Memory increase from 40.177 MB to 43.347 MB

Test case 2 - No saved data report

I clicked 10 times (1000 pdf created). Memory increase from 41.123MB to 42.835MB

Test case 3 - No saved data report and change location

I clicked 10 times (1000 pdf created). Memory increase from 52.412 to 54.063MB

Because I am developing a Windows Service and it runs 24/7, I expected that memory should not increase over time. My service runs 2 or 3 days and Crystal Report throws exception "Not enough memory for operation"

00:00:11,276 [Worker-8] ERROR e.PdfGenerator.PdfGeneratorJob - Error while generating pdf

CrystalDecisions.Shared.CrystalReportsException: Load report failed. ---> System.Runtime.InteropServices.COMException:

Not enough memory for operation.

   at CrystalDecisions.ReportAppServer.ClientDoc.ReportClientDocumentClass.Open(Object& DocumentPath, Int32 Options)

   at CrystalDecisions.ReportAppServer.ReportClientDocumentWrapper.Open(Object& DocumentPath, Int32 Options)

   at CrystalDecisions.ReportAppServer.ReportClientDocumentWrapper.EnsureDocumentIsOpened()

   --- End of inner exception stack trace ---

   at CrystalDecisions.ReportAppServer.ReportClientDocumentWrapper.EnsureDocumentIsOpened()

   at CrystalDecisions.CrystalReports.Engine.ReportDocument.Load(String filename, OpenReportMethod openMethod, Int16 parentJob)

   at CrystalDecisions.CrystalReports.Engine.ReportDocument.Load(String filename, OpenReportMethod openMethod)

Thank for all advice

Vi

former_member183750
Active Contributor
0 Kudos

The problem here is that we have no idea who is actually leaking the memory. The Load Report error, only points to the fact that you ran out of memory, not that it is any CR file leaking. It could be a CR file, but it could also be any one of the many MS dependencies, printer driver, database client runtime, etc. One utility that may tell you who is leaking is Rational Purify. But note that tracing the source of the leak is not easy. E.g.; Purify may report a CR dll, but the actual leak may be happening in a VC++ dependency dll that the CR dll may be using. Additionally, minor leaks are notoriously hard to resolve and even if we proved the leak is due to a CR dll, getting it fixed will more than likely be a futile effort. So, what is a possible solution? recycle your service once every 24 hours(?). Another thing I'd like you to do on your reports is enable the "No Printer" option (File | Page Setup), this will decrease possible contributions to the mem leak from the printer driver.

Other than that, if after using something like Purify, you still think it is a CR issue, I'd recommend creating a phone support case here:

Crystal Single Case Technical Support - SAP Business Objects US Online Store | SAP Online Store

- Ludek

0 Kudos

Hi Vi,

We do take memory leak seriously but as you can see below.... Cr is the least of problem...

I downloaded a trial version of Rational Purify and here's the results:

Purify for Windows,

(C) Copyright IBM Corporation. 1992, 2012. All Rights Reserved.

Version 7.0.1.0-003  Evaluation 32-bit ; Build: 20120705.2308;

Windows Server 2008 R2 Enterprise 6.1 7601  Multiprocessor Free

Instrumenting:

      CrystalMemleak.exe 6144 bytes

Purify: While processing file C:\CrystalMemleak\bin\Release\CrystalMemleak.exe:

Warning: This native code executable statically links managed or mixed code module(s).

Purify does not support this configuration when inclusive instrumentation

is used.For more info, see the topic "Inclusive Instrumentation" in the Purify

online help.

      NTDLL.DLL    1292192 bytes

      ADVAPI32.DLL 640512 bytes

      ADVAPI32.DLL 640512 bytes

      MSCOREE.DLL  297808 bytes

      MSVCRT.DLL   690688 bytes

Purify: While processing file C:\Windows\SysWOW64\MSVCRT.DLL:

Note: Instrumentation repeating with 7 additional entry points.

      KERNELBASE.DLL 274944 bytes

      SECHOST.DLL  92160 bytes

      SECHOST.DLL  92160 bytes

      KERNEL32.DLL 1114112 bytes

      RPCRT4.DLL   663552 bytes

      RPCRT4.DLL   663552 bytes

      PCWUM.DLL    33280 bytes

      PCWUM.DLL    33280 bytes

      CRYPTSP.DLL  78848 bytes

      CRYPTSP.DLL  78848 bytes

      SSPICLI.DLL  96768 bytes

      SSPICLI.DLL  96768 bytes

      CRYPTBASE.DLL 36864 bytes

      CRYPTBASE.DLL 36864 bytes

As you can see CR is leaking 6144 bytes

Nothing we can do about this, I doubt R&D will look for 6144 bytes...

Don

Answers (0)