tracemalloc分析內存使用情況與泄露方式
1.概述
python內存管理是通過引用計數執(zhí)行的,如果指向某個對象的引用全部過期,那么受引用的對象就可以從內存中清除,從而給其他數據騰出空間。
理論上講,python開發(fā)不用擔心程序如何分配和釋放內存,因為python系統(tǒng)本身以及Cpython運行環(huán)境會自動處理這些問題。
但實際情況程序會因為沒有及時釋放不再需要引用的數據耗盡內存。下面通過一些方法來看下內存使用情況。
2.查看gc引用對象總數
下面是被測試代碼,這個代碼可以創(chuàng)建對象,在gc中產生引用對象。
import os
class MyObject:
def __init__(self):
self.data = os.urandom(100)
def get_data():
values = []
for _ in range(100):
obj = MyObject()
values.append(obj)
return values
def run():
deep_values = []
for _ in range(100):
deep_values.append(get_data())
return
下面的代碼用來輸出當前gc引用對象的數量
import gc
# 獲取運行前gc引用對象數量
found_objects = gc.get_objects()
print('Before:', len(found_objects))
# 導入待測試模塊
import waste_memory
# 運行待測試代碼的函數
hold_reference = waste_memory.run()
# 獲取運行代碼后gc引用對象數量
found_objects = gc.get_objects()
print('After: ', len(found_objects))
for obj in found_objects[:5]:
print(repr(obj)[:100])
print('...')
運行上面的代碼,下面是gc引用的對象總數。
Before: 28834 After: 28923
3.tracemalloc查看內存分配情況
3.1.查看內存分配情況
上面只輸出了gc的總數,對于分析內存分配情況沒有太多的指導意義,tracemalloc模塊能夠追溯到分配它的位置,因此我們可以在之前模塊前后對內存使用情況做個快照,分析兩個快照之間的區(qū)別。
下面是被測試代碼
import tracemalloc
tracemalloc.start(10) # Set stack depth
time1 = tracemalloc.take_snapshot() # Before snapshot
import waste_memory
x = waste_memory.run() # Usage to debug
time2 = tracemalloc.take_snapshot() # After snapshot
stats = time2.compare_to(time1, 'lineno') # Compare snapshots
for stat in stats[:3]:
print(stat)
運行上面的代碼,從結果中可以看出,每一條記錄都有size與count指標,用來表示這行代碼所分配的對象占用多少內存,以及對象的數量。
通過對比就能發(fā)現占用內存較多的對象是由那幾行代碼分配的。
/waste_memory.py:11: size=5120 B (+5120 B), count=80 (+80), average=64 B /waste_memory.py:14: size=4424 B (+4424 B), count=79 (+79), average=56 B /waste_memory.py:9: size=1704 B (+1704 B), count=8 (+8), average=213 B
3.2.查看棧信息
tracemalloc還可以打印棧的追蹤信息,下面把程序中分配內存最多的那行代碼所對應的棧追蹤信息打印出來,看看程序是沿著哪條路徑觸發(fā)這行代碼的。
import tracemalloc
tracemalloc.start(10)
time1 = tracemalloc.take_snapshot()
import waste_memory
x = waste_memory.run()
time2 = tracemalloc.take_snapshot()
stats = time2.compare_to(time1, 'traceback')
top = stats[0]
print('Biggest offender is:')
# 打印棧信息
print('\n'.join(top.traceback.format()))
運行上面的代碼
Biggest offender is:
File "/with_trace.py", line 14
x = waste_memory.run()
File "/waste_memory.py", line 23
deep_values.append(get_data())
File "/waste_memory.py", line 16
obj = MyObject()
File "/waste_memory.py", line 11
self.data = os.urandom(100)
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
python解決No?module?named?pip問題兩種方法
當出現No module named pip錯誤時,表明您的Python環(huán)境缺少pip模塊,下面這篇文章主要給大家介紹了關于python解決No?module?named?pip問題的兩種方法,需要的朋友可以參考下2024-01-01

