tracemalloc:无法捕获更高的帧
tracemalloc: cannot capture higher frames
我正在尝试使用 tracemalloc
提取代码帧来找出大型项目中的内存泄漏。但是,我无法获得超过一个最深的框架,这对于具有大量依赖项和无数嵌套调用的大型项目是无用的。根据the docs,我尝试使用:
tracemalloc.start
限制参数
PYTHONTRACEMALLOC
环境变量
-X tracemalloc
命令行参数
tracemalloc.get_traceback_limit()
显示我设置的正确数字。但是,我仍然只得到每个 Traceback 对象的一帧。它在不同机器上的 Python 版本 3.8.5 和 3.9.7 上工作相同。这里有什么问题??我该如何解决这个问题?
这是最小的例子:
import os
import tracemalloc
def get_top_malloc(trace_number):
snapshot = tracemalloc.take_snapshot()
snapshot = snapshot.filter_traces((
tracemalloc.Filter(False, "<frozen importlib._bootstrap>"),
tracemalloc.Filter(False, "<unknown>"),
))
top_stats = snapshot.statistics("lineno")
msg = []
if trace_number > 0:
msg.append(f"Top malloc {trace_number} lines")
for index, stat in enumerate(top_stats[:trace_number]):
msg.append(f"#{index}: {stat.size // 1024} KB, {stat.count} times")
print(stat.traceback._frames) # Only single frame is here!
print(dir(stat.traceback))
msg.extend(line for line in stat.traceback.format(limit=16))
other = top_stats[trace_number:]
if other:
size = sum(stat.size for stat in other)
msg.append(f"{len(other)} other: {size // 1024} KB")
total = sum(stat.size for stat in top_stats)
msg.append(f"Total allocated size: {total // 1024 // 1024} MB")
return "\n".join(msg)
storage = {}
def func2():
def func3():
value = '3.1415926535897932384626433832795028841971'
value = value * 4096
storage['pi'] = value
func3()
def func1():
func2()
if __name__ == "__main__":
tracemalloc.start(4)
print(f"\n-- Limit: {tracemalloc.get_traceback_limit()}")
func1()
print(f"\n-- {get_top_malloc(1)}")
tracemalloc.stop()
我找到了解决方案,它很简单但并不明显。快照对象的 statistics(...)
方法采用 key_type
参数,该参数用于按文件 ("filename"
)、文件+行 ("lineno"
) 或按整个追溯("traceback"
)。我使用默认值 "lineno"
过滤掉每个回溯的最后一帧除外的所有内容,因此切换到 "traceback"
选项解决了问题并允许我获得我需要的所有帧 :)
我正在尝试使用 tracemalloc
提取代码帧来找出大型项目中的内存泄漏。但是,我无法获得超过一个最深的框架,这对于具有大量依赖项和无数嵌套调用的大型项目是无用的。根据the docs,我尝试使用:
tracemalloc.start
限制参数PYTHONTRACEMALLOC
环境变量-X tracemalloc
命令行参数
tracemalloc.get_traceback_limit()
显示我设置的正确数字。但是,我仍然只得到每个 Traceback 对象的一帧。它在不同机器上的 Python 版本 3.8.5 和 3.9.7 上工作相同。这里有什么问题??我该如何解决这个问题?
这是最小的例子:
import os
import tracemalloc
def get_top_malloc(trace_number):
snapshot = tracemalloc.take_snapshot()
snapshot = snapshot.filter_traces((
tracemalloc.Filter(False, "<frozen importlib._bootstrap>"),
tracemalloc.Filter(False, "<unknown>"),
))
top_stats = snapshot.statistics("lineno")
msg = []
if trace_number > 0:
msg.append(f"Top malloc {trace_number} lines")
for index, stat in enumerate(top_stats[:trace_number]):
msg.append(f"#{index}: {stat.size // 1024} KB, {stat.count} times")
print(stat.traceback._frames) # Only single frame is here!
print(dir(stat.traceback))
msg.extend(line for line in stat.traceback.format(limit=16))
other = top_stats[trace_number:]
if other:
size = sum(stat.size for stat in other)
msg.append(f"{len(other)} other: {size // 1024} KB")
total = sum(stat.size for stat in top_stats)
msg.append(f"Total allocated size: {total // 1024 // 1024} MB")
return "\n".join(msg)
storage = {}
def func2():
def func3():
value = '3.1415926535897932384626433832795028841971'
value = value * 4096
storage['pi'] = value
func3()
def func1():
func2()
if __name__ == "__main__":
tracemalloc.start(4)
print(f"\n-- Limit: {tracemalloc.get_traceback_limit()}")
func1()
print(f"\n-- {get_top_malloc(1)}")
tracemalloc.stop()
我找到了解决方案,它很简单但并不明显。快照对象的 statistics(...)
方法采用 key_type
参数,该参数用于按文件 ("filename"
)、文件+行 ("lineno"
) 或按整个追溯("traceback"
)。我使用默认值 "lineno"
过滤掉每个回溯的最后一帧除外的所有内容,因此切换到 "traceback"
选项解决了问题并允许我获得我需要的所有帧 :)