プログラムを中心とした個人的なメモ用のブログです。 タイトルは迷走中。
内容の保証はできませんのであしからずご了承ください。

2022/02/26

[Python] tracemalloc を使ってメモリリークの発生箇所を特定する

event_note2022/02/26 6:37

メモリの使用量が綺麗に右肩上がりになっているアプリがあったので、メモリリークの発生箇所を特定する方法を調べてみたところ、標準モジュールの tracemalloc で出来そうなので、使ってみました。

tracemalloc については以下のページを参考にさせていただきました。

環境

  • Python 3.8.10

サンプルコード

スレッド化し、5秒ごとにメモリ使用量トップ10と、メモリ増加量トップ10を表示するようにしてみました。

import tracemalloc
import time
from datetime import datetime
from threading import Thread

class MemoryCheker:

    def __init__(self):
        self.__is_running = False
        self.__snapshot = None

    def start(self):
        print(f'{self.__class__.__name__} start')
        self.__is_running = True
        self.__thread = Thread(target=self.__run)
        self.__thread.start()

    def stop(self):
        print(f'{self.__class__.__name__} stopping')
        self.__is_running = False
        self.__thread.join()
        print(f'{self.__class__.__name__} stopped')

    def __run(self):

        while self.__is_running:
            snapshot = tracemalloc.take_snapshot()
            top_stats = snapshot.statistics('lineno')
            print(f'[ Top 10 : {datetime.now()}]')
            for stat in top_stats[:10]:
                print(stat)
            if self.__snapshot != None:
                top_stats = snapshot.compare_to(self.__snapshot, 'lineno')
                print('[ Top 10 Difference ]')
                for stat in top_stats[:10]:
                    print(stat)
            self.__snapshot = snapshot
            time.sleep(5)

if __name__ == '__main__':

    tracemalloc.start()
    memory_checker = MemoryChecker()
    memory_checker.start()
    
    # do something
    
    memory_checker.stop()

これでメモリリークしている箇所にあたりをつけ、原因を特定することができました。