tkinter memory leak

Asked 1 years ago, Updated 1 years ago, 320 views

In the GUI application using tkinter, when you click on the app, you communicate with the outside world and update the screen based on that information.
I found that the amount of memory gradually increases when I click it repeatedly in the auto-run app (I use the auto-run app with a MacroRecorder, not my own).
手動 Manually clicking causes memory growth as well.

Since Git is managing the version, we tracked where the symptom started, but there was only a small difference between the version where the symptom occurred and the version where it did not occur.
The memory does not stop rising when you rewrite the version where the symptom started to occur (re-write the source code to the version where the symptom did not occur).
If you do not click and the state does not change, there is no particular increase in memory.

If you revert the version with the git reset --hard command, the memory does not go up.
The difference in code in git history is obvious at a glance, so there is no need to manually rewrite it wrong or overlook it.

It's a big code as a whole, so I can't write it down.
Running on several multi-processes, Windows Performance Monitor found that the GUI process was experiencing memory spikes following each process.

When I return the source code, the symptom does not stop and I do not think the code is causing the problem.
So, since there's no way to fix the code, is there anything else that big applications need to do, such as secure memory?

python tkinter memory-leaks

2023-01-26 14:36

1 Answers

I think it has been resolved, so I will write it down in my answer.

We created the following classes using tracemalloc:


import datetime
importos
import time
import tracemalloc


class trace_memory():
    def__init__(self, interval_time: int=1*60, top:int=10):
        self.b_snap_malloc = None
        self.a_snap_malloc = None

        self.timer = None
        self.trace_interval = interval_time#sec
        self.top_slice=top

        file_dir=os.getcwd()+'/logs'
        self.file_path=file_dir+'/trace_memory.log'

        os.madeirs (file_dir, exist_ok = True)

        ifos.path.exists(self.file_path):
            with open(self.file_path, 'w') asf:
                pass

    def start (self):
        tracemalloc.start()

    default (self):
        if self.timer is None:
            self.timer = time.time()
            if self.b_snap_malloc is None:
                self.b_snap_malloc=tracemalloc.take_snapshot()
        else:
            if(time.time()-self.timer)>=self.trace_interval:
                self.timer = time.time()

                timestamp=datetime.datetime.now()

                time_format = '%Y-%m-%d%H:%M:%S.%f'
                timestamp=timestamp.strftime(time_format)

                self.a_snap_malloc=tracemalloc.take_snapshot()
                top_stats=self.a_snap_malloc.compare_to(
                    self.b_snap_malloc, 'lineno')

                with open(self.file_path, "a") asf:
                    f.write(f'{timestamp}:[memory trace differences]\n')
                    for stat intop_stats [:self.top_slice]:
                        f.write(f'{timestamp}:{stat}\n')

                self.b_snap_malloc=tracemalloc.take_snapshot()


if__name__=='__main__':
    inst=trace_memory()
    inst.start()
    inst.trace()

By default, the log prints the TOP10 with a large difference in memory usage every minute.
The initialization argument allows you to specify the interval time and the TOP number.
in a looping class or function,
·Create an instance of trace_memory before looping
·Call the trace_memory.start() method before the loop.

inside the looping processing ·Describe to call trace_memory.trace() method

In this case, the reason was that the mousewheel event bind to the Canvas widget was performed for each screen update process.Changed this to bind only when screen changes require updates.

If tkinter tries to bind an event dynamically to a widget, it may not internally discard past methods that bind to the same event.As mentioned in the symptom, it is not certain that there is a leak, and it seems that it is caused by irrelevant changes.
·Putting the unbind method before the bind does not solve the problem.
·Release garbage collection will not solve the problem.

In a different process, we have also identified a leak that causes the handle count to rise, and we have found that each time the dialog is displayed or hidden, the handle is secured and not released for the image file to the image file used during the pop-

When using tkinter, it is recommended that you check the memory and handle changes on a performance monitor in a recurring pattern with some user action.
With a tool called ProcessExplorer, you can observe specific handle targets.


2023-01-26 14:57

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.