Home Datapipelines
New Blog Post: Email: Multi-Service

Memory leak with DB JIT's

In our app when we run a SQL statement our database.connection method for returning the ADO SQL connection to be used creates a new connection object per 'database connection' per thread if one doesn't exist yet. We also keep a track of connections assigned to each 'database' object and another list/dictionary for ADO connections created in a thread so that we can track and detect developer failure to close and cleanup. We normally close the connection when it's finished with and then just before thread exit call 'releaseThreadsConnections' which checks to see that connections for the thread have all been closed and free'd, when they haven't it throws an assert and cleans up.

I haven't been able to find any events or similar suitable place that I can hook into to do a connection close (within the correct thread report builder runs the JIT queries in), nor where I can call our 'releaseThreadsConnections'. Note that they could be called sequentially in the same event. Are you able to advise if there is anywhere suitable?

The Developers Guide hasn't been any help and I've tried looking for your online help but can't find it and the downloadable WinHelp and HTML help at https://www.digital-metaphors.com/download/documentation/#OnlineHelp don't work on my computer

Comments

  • Hi Mark,

    I recommend using a DataModule (or Form) to define a thread-safe 'ReportModule' that acts as a container for generating reports in threads.

    The ReportModule can contain (Own) the Report, JITPipeline and any other components required to generate the report.

    To generate a report, create a ReportModule instance, generate the report, free the ReportModule instance.

    Implement the ReportModule OnCreate. OnDestroy events to handle special pre and post cleanup. If you still need more customization, define TmyReportModule methods and events.



    Best regards,

    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com
  • Hi Nard

    The RBuilder.chm help is working again today on my PC, the previous two days it would show the index list, search list etc but if you clicked on an item no page/details for it would show up.

    It looks like there's no help for TppReportModule?

    We mostly don't control what tables/JITs/Delphi Functions are in the reports so apart from some always used items we don't specifically know what JITs etc were used - we do supply a base lot of reports to customers and they then customise as they desire. Many of the reports run using report builder back ground threading so Just to confirm, the TppReportModule OnDestroy will run in the correct background thread that each report used and therefore with the list of connections created in that thread that we maintain we will be able to correctly clean them up? I didn't see where use of this was implemented in the report builder page thread execution method and child calls but may have easily missed it?

    One of the things we would also like to do is move a lot of our app logic from Windows desktop app into a REST server - we've already started doing this. To get reporting working in it we would need to support multiple simultaneous REST requests, each on it's own thread to the same and/or different databases and each REST request thread could be running multiple reports, potentially using report builder background threads as server and client will be using common code where ever possible. Our predefined TDataModule subclass has some ADO connection, data sources, report builder pipelines fields etc. I had assumed we would need to create TDataModule objects on the fly so that simultaneous REST requests wouldn't be blocked. Are there likely to be any issues with creating multiple TDataModule objects and running them in different threads?

  • Hi Mark,

    From Delphi create a new DataModule and add a Report and ADOConnection, name the class TmyReportModule

    TmyReportModule = class(TDataModule)
    ppReport1: TppReport;
    ADOConnection1: TADOConnection;
    private
    { Private declarations }
    public
    { Public declarations }
    end;

    Add any addition components required to generate the report

    Add any custom properties and methods you require

    ADO handles connection pooling automatically, you do not need to do anything.

    To generate a report, create a ReportModule instance, generate the report, free the ReportModule instance.


    Best regards,

    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com
  • Hi Mark,


    Screen Device (report preview)
    ---------------
    By default screen device generates pages in a background thread. To generate preview in the main thread set

    Report.PreviewFormSetings.UseBackgroundThread := False

    or

    Report.PreviewFormSettings.SinglePageOnly := True
    Try using one of the above properties to generate preview in the main thread.

    The RB Preview is interactive, it generates pages incrementally on demand. It re-generates pages when a Search condition is entered. It is not a place to destroy objects used by the report.


    REST Server
    ------------------
    A REST server will typically generate a file (PDF or other) and return it to client. RB file devices and the printer device generate pages in the thread from which Report.Print is called.

    Note: Pleas email support@ if you want to discuss RB source. Please do not post here. :)


    Best regards,

    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com
Sign In or Register to comment.