TMS MemInsight, Delphi runtime memory inspection: statistics and filters
Using TMS MemInsight is easy: drop a component on your form, set some properties and there you go. Altough the component and UI of TMS MemInsight are currently based on the VCL you can already use it in your FireMonkey (on Windows and without UI), Windows service or console applications or any other headless application, such as a TMX XData server. But in this blog, we dive deeper: TMS MemInsight has a wide API and offers all of its options and features by code. Let’s start by looking at some of the properties of the memory profiler first. To access it, as well as other parts of TMS MemInsight, use the units TMS.MI.Access and TMS.MI.Memory from within your code. These units contain some functions which serve as entry point to gain access to the interfaces needed to control tracing, filters as well as more advanced options like collecting memory statistics as it’s done within the UI. Another handy unit is TMS.MI.Core which offers some ready to use utility functions. You can enable/disable the profiler by setting it’s Active property. You can Suspend/Resume profiling for the current thread by calling the methods of the same name or exclude them completely to control and tune what is being traced. For this, TMS MemInsight also offers filters which allow for even more fine tuning. Filters can also be customized and attached and removed dynamically. The folder “Dev” contains a sample for such a filter which allows tracing of objects contained in certain units only. We will use it in our example below. Another useful method is SuspendMethod which disables tracing for the current thread until the current scope is exited. Usually this is, as the name suggests, the current method, although this has slightly changed in Delphi 11 Alexandria with the introduction of inline variables where the scope might be limited to the current begin/end block. The memory profiler includes three different filters. The Default filter allows to configure, which threads are being traced as well as setting the TraceTypes: mtString, mtObject, mtArray, mtRecord and mtUnknown. Beside of that you can, if your applications is build using run-time packages, select which package classes are shown. The IncludeFilter and ExcludeFilter allow fine grained tracing considering the class name of objects and supports pattern matching. This way you can limit the tracing to certain class names as well as class names matching something like “TYourPrefix*” or exclude class names matching similar patterns. All filters can be activated/deactivated by setting their Active property. You can store and reload these configurations for latter use. Let’s jump right into our first example: collecting memory statistics and dumping them into a file. Working with these statistics is, in almost all cases, my starting point when trying to understand why, where and what the application is consuming. As this is happening during run-time I can use the application, repeat certain functions and observe its behavior to isolate and concentrate on concrete spots. Limiting the tracing on these identified classes by using the above mentioned filters is also helpful. For the sake of this example we create five utility functions: InitializeProfiling, StartProfiling, StopProfiling, ResetStatistics and SaveToFile. InitializeProfiling will set up some default options and attach and configure the filter as well as the memory statistics. We also disable stack traces as […]
