memory_profiler 模塊被用於在逐行的基礎上,測量你代碼的內存使用率,也建議安裝 psutil 包,使得 memory_profile 模塊運行的更快
from memory_profiler import profile @profile(precision=6) def primes(n): if n == 2: return [2] elif n < 2: return [] s = range(3, n + 1, 2) mroot = n ** 0.5 half = (n + 1) / 2 - 1 i = 0 m = 3 while m <= mroot: if s[i]: j = (m * m - 3) / 2 s[j] = 0 while j < half: s[j] = 0 j += m i = i + 1 m = 2 * i + 3 return [2] + [x for x in s if x] len(primes(100000))
meliae會把某個時刻的內存給dump到一個文件中,然后再對該文件進行分析,當我們的某個python程序占用內存很大,可能有內存泄露發生時,可以使用該工具來進行檢測分析
Guppy (使用了Heapy):使用 guppy 包,你可以跟蹤每個類型在你代碼中每個階段(字符, 元組, 字典 等等)有多少對象被創建了,查看占用內存前十位變量的工具
objgraph模塊:該工具允許你查看內存中對象的數量,定位含有該對象的引用的所有代碼的位置。
.定位哪個對象引起內存泄漏 # -*- coding: utf-8 -*- import objgraph _cache = [] class OBJ(object): pass def func_to_leak(): o = OBJ() _cache.append(o) # do something with o, then remove it from _cache if True: # this seem ugly, but it always exists return _cache.remove(o) if __name__ == '__main__': objgraph.show_growth() try: func_to_leak() except: pass print '********after call func_to_leak*********' objgraph.show_growth() 運行結果(我們只關心后一次 show_growth 的結果)如下 wrapper_descriptor 1196 +1196 function 1187 +1187 builtin_function_or_method 739 +739 method_descriptor 635 +635 dict 539 +539 weakref 457 +457 tuple 364 +364 getset_descriptor 306 +306 list 232 +232 member_descriptor 227 +227 ********after call func_to_leak********* wrapper_descriptor 1205 +9 getset_descriptor 310 +4 member_descriptor 230 +3 weakref 459 +2 dict 541 +2 OBJ 1 +1 從運行結果可以發現,調用函數之后,增加了一個類 OBJ 的實例,然而理論上函數調用結束之后,所有在函數作用域(local)中聲明的對象都改被銷毀,因此這里就存在內存泄露。
- 顯示占據python程序內存的頭N個對象
- 顯示一段時間以后哪些對象被刪除活增加了
- 在我們的腳本中顯示某個給定對象的所有引用
============快速生成陌生代碼的函數調用關系