使用 tracemalloc 进行内存分析
使用 tracemalloc 跟踪内存分配并查找内存泄漏。
使用 tracemalloc 进行内存分析 是 CoddyKit 上的免费 Python Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Python Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Python Academy 课程共包含 4 节课。
什么是 tracemalloc?
tracemalloc 是一个标准库模块,可按文件和行号跟踪 Python 的内存分配。
import tracemalloc
tracemalloc.start()
x = [i for i in range(100_000)]
current, peak = tracemalloc.get_traced_memory()
tracemalloc.stop()
print(f"Current: {current/1024:.1f} KB")
print(f"Peak: {peak/1024:.1f} KB")获取快照
快照会捕获某个时间点的所有当前内存分配。比较两个快照,可以找出这两个时间点之间分配的内存。
import tracemalloc
tracemalloc.start()
snap1 = tracemalloc.take_snapshot()
data = [{"key": str(i)} for i in range(10_000)]
snap2 = tracemalloc.take_snapshot()
stats = snap2.compare_to(snap1, "lineno")
for stat in stats[:5]:
print(stat)筛选快照
将统计信息筛选为仅显示应用程序代码,并排除标准库。
import tracemalloc
tracemalloc.start()
leak_function()
snap = tracemalloc.take_snapshot()
filters = [tracemalloc.Filter(True, "*/myapp/*")]
stats = snap.filter_traces(filters).statistics("lineno")
for stat in stats[:10]:
print(stat)主要内存分配位置
使用 snapshot.statistics("lineno") 或 "traceback",按代码行或完整回溯查看占用内存最多的位置。
import tracemalloc
tracemalloc.start(nframe=10) # track 10 frames deep
big_list = [i**2 for i in range(500_000)]
snap = tracemalloc.take_snapshot()
for stat in snap.statistics("traceback")[:3]:
print(stat)
for line in stat.traceback.format():
print(" ", line)查找内存泄漏
在疑似发生泄漏的位置前后分别获取快照并进行比较。如果两个快照之间的统计数据不断增长,就表明存在内存泄漏。
import tracemalloc
tracemalloc.start()
snap_before = tracemalloc.take_snapshot()
for _ in range(100):
suspected_leaky_function()
snap_after = tracemalloc.take_snapshot()
diff = snap_after.compare_to(snap_before, "lineno")
for stat in diff[:5]:
print(stat)get_traced_memory()
tracemalloc.get_traced_memory() 返回以字节为单位的 (current, peak),适用于轻量级的前后对比检查。
import tracemalloc
tracemalloc.start()
before, _ = tracemalloc.get_traced_memory()
do_something()
after, peak = tracemalloc.get_traced_memory()
tracemalloc.stop()
print(f"Delta: {(after-before)/1024:.1f} KB, Peak: {peak/1024:.1f} KB")memory_profiler
memory_profiler 提供逐行内存使用情况,类似于用于 CPU 分析的 line_profiler。
# pip install memory_profiler
from memory_profiler import profile
@profile
def build_data():
data = [i**2 for i in range(100_000)]
filtered = [x for x in data if x % 2 == 0]
return filtered
build_data()
# python -m memory_profiler script.pymemray
memray(由 Bloomberg 开发)是一款快速的 Python 内存分析器,可输出火焰图。
# pip install memray
# python -m memray run script.py
# python -m memray flamegraph memray-script.py.bin
# Generates an interactive HTML flamegraph
# showing allocations by call stack降低内存使用量
常见方法包括:使用生成器代替列表、使用 __slots__、使用 array 模块存储数值数据、使用 numpy 数组,以及避免让闭包长期持有大型对象。
# Instead of:
data = [process(x) for x in huge_list] # all in memory
# Use a generator:
def gen_data(lst):
for x in lst:
yield process(x)
for item in gen_data(huge_list):
consume(item) # one at a timesys.getsizeof()
sys.getsizeof(obj) 返回对象本身使用的内存量(以字节为单位;这是浅层大小,不包括被引用的对象)。
import sys
print(sys.getsizeof([])) # 56
print(sys.getsizeof([1,2,3])) # 88
print(sys.getsizeof("hello")) # 54
print(sys.getsizeof({})) # 64
# For deep size, use recursive measurement:
def deep_size(obj):
return sys.getsizeof(obj) + sum(
sys.getsizeof(v) for v in vars(obj).values()
if hasattr(obj, "__dict__")
)在生产环境中进行分析
在生产环境中使用 tracemalloc 时,请限制 nframes,以尽量降低开销。将快照保存到文件中,以便离线分析。
import tracemalloc, pickle
tracemalloc.start(nframe=5) # low overhead
# ... serve some requests ...
snap = tracemalloc.take_snapshot()
with open("snap.pkl","wb") as f:
pickle.dump(snap, f)
# Analyse later offline快速检查
tracemalloc.get_traced_memory() 返回的两个值分别表示什么?
回顾
使用 tracemalloc.start() 和快照查找内存泄漏。使用 compare_to() 比较快照。使用 memory_profiler 查看逐行内存使用情况,使用 memray 生成火焰图。使用生成器、__slots__ 和 NumPy 数组来减少内存使用量。
常见问题解答
「使用 tracemalloc 进行内存分析」课时是免费的吗?
是的 — 「使用 tracemalloc 进行内存分析」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Python Academy 课程的其余内容,请升级到 CoddyKit PRO。 Python Academy 课程共包含 4 节课。
「使用 tracemalloc 进行内存分析」这节课中我会学到什么?
使用 tracemalloc 跟踪内存分配并查找内存泄漏。 你通过在浏览器中直接运行的动手代码来练习 Python Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Python Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Python Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「使用 tracemalloc 进行内存分析」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Python Academy 课中编写并运行代码吗?
能。每节 Python Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- CPython 引用计数
- 垃圾回收器与循环引用
- 使用 cProfile 和 line_profiler 进行性能分析
- 使用 tracemalloc 进行内存分析