shineworld 73 Posted July 12, 2022 (edited) Hi all. What I love of Delphi is memory management and overall the integration of FastMM and related memory leak management. All my projects are Memory Leak Free (just thanks to reports of FastMM which permits me to create a better code). Now I'm migrating some programs to Python using DelphiVCL and I'm falling into odd memory leaks. In a Python (3.9.12) application that uses DelphiVCL (0.1.40) I've noticed a continuous memory leak in some simple operations with VCL objects like Checkbox. I've attached a very simple Python program that uses a Timer to constantly update the Enabled state of a Checkbox. In the sample, I've also added a const to enable a tracemalloc and confirm the continue grow of memory used by <Checkbox>.Enabled = True # enable/disable tracemalloc to exclude the memory impact of tracemalloc TRACEMALLOC_ENABLED = False By default, TRACEMALLOC_ENABLED is set to False to remove any impact of tracemalloc framework. If enabled, the first mouse down on the form capture the BASE snapshot of memory. Any following mouse down, report on console the comparison of current snapshot with the first. Initially, tracemalloc internals is in the top ten results, but after some time Checkbox1.Enabled = True gain the top. If I disable the interesting lines, commenting on them, any memory leak disappears: def __on_timer(self, sender): """ self.CheckBox1.Enabled = True self.CheckBox1.Enabled = True self.CheckBox1.Enabled = True self.CheckBox1.Enabled = True self.CheckBox1.Enabled = True self.CheckBox1.Enabled = True self.CheckBox1.Enabled = True self.CheckBox1.Enabled = True self.CheckBox1.Enabled = True self.CheckBox1.Enabled = True self.CheckBox1.Enabled = True self.CheckBox1.Enabled = True self.CheckBox1.Enabled = True """ I've placed many CheckBox1.Enabled to exasperate the case-test but usually, I do this for a lot of controls in update events. This is the memory usage captured with Process Explorer on running Python process with TRACEMALLOC_ENABLED = False: test.zip Edited July 12, 2022 by shineworld typo Share this post Link to post
pyscripter 689 Posted July 14, 2022 (edited) Just to clarify. a) No memory leakage happens if your timer routine is: def __on_timer(self, sender): pass b) The increase in memory usage increases indefinitely when self.CheckBox1.Enabled = True is called inside the timer routine. c) Could this be tracemalloc overhead? (the memory traces take memory space). For example does the memory gets released with tracemalloc.clear_traces() (tracemalloc — Trace memory allocations — Python 3.10.5 documentation) d) Do you see Windows memory allocated to the process increasing without tracemalloc Edited July 14, 2022 by pyscripter Share this post Link to post
shineworld 73 Posted July 15, 2022 (edited) a) YES without any code in __on_timer(...) I have no memory leaks. b) YES if I add any operations with a checkbox in __on_timer() the memory leaks begin. c) I've used a const to DISABLE trace malloc os I can exclude that memory-leaks depends by it. d) YES the graphical images posted are without the use of trace malloc but are a bird-eye view of the python windows process memory consumption. In the test, I've checked only CheckBox.Enabled, to be simple, but in the full project, I've got some memory leaks also in <vcl>.Caption = etc. The memory leaks began when I switched from PySimpleGUI to DelphiVCL UI. The project uses a lot of DelphiVCL components so, in running time, the memory leak increases a lot. A program, at first start, uses 139MB, but after two hours it reaches 700MB or memory usage and trace malloc suggests that is in DelphiVCL. In the below video, I try to show the behavior. The system is simple. An embedded board with a camera, in this case, an RPI4, captures the camera frames and implements a server service to obtain an IP-CAMERA. To simplify the case is written in Python. A PC program, with Python + DelphiVCL + OpenCV + Skia connects to IP-Camera, gets frames, and applies code to elaborate it. In the test code, I've added trace malloc with a first memory snapshot (take_snaphot) at the start. When I press the middle button on the frame view I capture a memory snapshot that I compare with the start snapshot to show the top 10 memory consumers. It is normal that no VCL objects reach temporary the top because I capture some frames and I take them for future uses but looking on the counter is low. What I see is the usage memory and allocated counter increase continuously in some DelphiVCL operations. To be honest, I don't know so wheel Python and inners, I've begun to use it some time ago to try to port some apps to Python language on customer request, I'm a Delphi developer. So I can have mistakes on how to use tracemalloc to catch memory leaks. https://www.youtube.com/watch?v=rhUniVnXgEQ Edited July 15, 2022 by shineworld Share this post Link to post
pyscripter 689 Posted July 16, 2022 (edited) This was due to a bug (TPyDelphiObject.SetAttrO causes memory leak · Issue #368 · pyscripter/python4delphi (github.com)) which is now fixed. It may take some time for the fix to be reflected in the pip installable delphivcl, but you can always compile your own delphivcl.pyd from the github sources. @shineworldThanks for discovering the issue. Edited July 16, 2022 by pyscripter 1 Share this post Link to post