亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

對(duì)python程序內(nèi)存泄漏調(diào)試的記錄

 更新時(shí)間:2018年06月11日 14:41:12   作者:ybdesire  
今天小編就為大家分享一篇對(duì)python程序內(nèi)存泄漏調(diào)試的記錄,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧

問(wèn)題描述

調(diào)試python程序時(shí),用下面這段代碼,可以獲得進(jìn)程占用系統(tǒng)內(nèi)存值。程序跑一段時(shí)間后,就能畫(huà)出進(jìn)程對(duì)內(nèi)存的占用情況。

def memory_usage_psutil():
 # return the memory usage in MB
 import psutil,os
 process = psutil.Process(os.getpid())
 mem = process.memory_info()[0] / float(2 ** 20)
 return mem

發(fā)現(xiàn)進(jìn)程的內(nèi)存占用一直再上漲,而這從邏輯上來(lái)說(shuō)是不正常的,所以想到程序可能發(fā)生了Memory Leak。

python程序的Mem Leak

python程序不可能像C/C++一樣出現(xiàn)malloc了的內(nèi)存沒(méi)有free這樣的Memory Leak。但也會(huì)遇到“邏輯上沒(méi)free”的情況,如下代碼所示。

def foo(a=[]):
 a.append(time.time())
 return a

參數(shù)a這樣可迭代的對(duì)象,稍不注意,它就能增長(zhǎng)的很快。說(shuō)白了,python的Memory Leak,就是“進(jìn)程占用的內(nèi)存莫名其妙一直再升高”。進(jìn)程占用內(nèi)存一直升高,與邏輯預(yù)期不一致,就可能發(fā)生了Memory Leak。

以下面程序?yàn)槔f(shuō)明Memory Leak調(diào)試的過(guò)程:

def memory_usage_psutil():
 # return the memory usage in MB
 import psutil,os
 process = psutil.Process(os.getpid())
 mem = process.memory_info()[0] / float(2 ** 20)
 return mem

def get_current_obj(a=[]):
 a.append([0]*1000)
 return a

def main(): 
 obj = []
 for i in range(10000):
 obj = get_current_obj(obj)
 if(i%100==0):
  print(memory_usage_psutil())

if __name__=='__main__':
 main()

調(diào)試過(guò)程

用pmap -x [pid]查看進(jìn)程占用的堆內(nèi)存大小

首先想到,會(huì)不會(huì)是上面用的memory_usage_psutil函數(shù)統(tǒng)計(jì)錯(cuò)誤呢。

先運(yùn)行程序,再用pmap查看,發(fā)現(xiàn)進(jìn)程內(nèi)存占用確實(shí)很高。多次執(zhí)行該命令,也可以發(fā)現(xiàn)內(nèi)存一直升高。

強(qiáng)制執(zhí)行GC(gc.collect())

在需要執(zhí)行GC的地方加上gc.collect()

def main(): 
 obj = []
 for i in range(10000):
 obj = get_current_obj(obj)
 import gc;gc.collect()
 if(i%100==0):
  print(memory_usage_psutil())

可以看到,強(qiáng)制GC后,程序執(zhí)行變慢,但內(nèi)存依然不斷升高。

使用memory_profiler查看

安裝memory_profiler

pip install -U memory_profiler

用@profile修飾需要查看內(nèi)存的函數(shù)

@profile
def main(): 
 obj = []
 for i in range(10000):
 obj = get_current_obj(obj)
 if(i%100==0):
  print(memory_usage_psutil())

用如下命令運(yùn)行程序

python -m memory_profiler main.py

可以看到程序執(zhí)行完成后,輸出結(jié)果如下

Line # Mem usage Increment Line Contents
================================================
 12 28.570 MiB 0.000 MiB @profile
 13    def main():
 14 28.570 MiB 0.000 MiB obj = []
 15 106.203 MiB 77.633 MiB for i in range(10000):
 16 106.203 MiB 0.000 MiB  obj = get_current_obj(obj)
 17 106.203 MiB 0.000 MiB  if(i%100==0):
 18 105.445 MiB -0.758 MiB  print(memory_usage_psutil())

這樣就能看到導(dǎo)致內(nèi)存上漲最快的那幾行代碼。

用guppy查看python對(duì)象占用的堆內(nèi)存大小

將main修改如下,即可查看python對(duì)堆內(nèi)存的占用量。

def main(): 
 obj = []
 for i in range(10000):
 obj = get_current_obj(obj)
 if(i%100==0):
  print(memory_usage_psutil())
  from guppy import hpy;hxx = hpy();heap = hxx.heap()
  print(heap)

下面就是輸出結(jié)果,python程序中各個(gè)對(duì)象對(duì)內(nèi)存的占用從大到小排列。

 Index Count % Size % Cumulative % Kind (class / dict of class)
 0 10124 22 81944416 95 81944416 95 list
 1 16056 34 1325464 2 83269880 96 str
 2 9147 20 745616 1 84015496 97 tuple
 3 102 0 366480 0 84381976 98 dict of module
 4 287 1 313448 0 84695424 98 dict of type
 5 2426 5 310528 0 85005952 98 types.CodeType
 6 2364 5 283680 0 85289632 99 function
 7 287 1 256960 0 85546592 99 type
 8 169 0 192088 0 85738680 99 dict (no owner)
 9 123 0 142728 0 85881408 99 dict of class

可以從結(jié)果中看到,95%的進(jìn)程內(nèi)存,都被一個(gè)list占用。

還可以通過(guò)下面這種方式,查看這個(gè)占內(nèi)存最大的list中的數(shù)據(jù)類(lèi)型。

from guppy import hpy;hxx = hpy();byrcs = hxx.heap().byrcs; byrcs[0].byid

關(guān)于guppy的詳細(xì)用法,可以看這里(http://smira.ru/wp-content/uploads/2011/08/heapy.html)。

以上這篇對(duì)python程序內(nèi)存泄漏調(diào)試的記錄就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Python實(shí)現(xiàn)自動(dòng)收集參數(shù)的技巧分享

    Python實(shí)現(xiàn)自動(dòng)收集參數(shù)的技巧分享

    在Python中,充分利用函數(shù)參數(shù)的自動(dòng)收集和靈活處理,是寫(xiě)出高效且易維護(hù)代碼的關(guān)鍵之一,本文將深入研究Python函數(shù)參數(shù)的收集方式,感興趣的小伙伴可以了解下
    2023-12-12
  • 利用Python的pandas數(shù)據(jù)處理包將寬表變成窄表

    利用Python的pandas數(shù)據(jù)處理包將寬表變成窄表

    這篇文章主要介紹了利用Python的pandas數(shù)據(jù)處理包將寬表變成窄表,文章通過(guò)圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-09-09
  • Java如何交換字符串中兩個(gè)位置的值

    Java如何交換字符串中兩個(gè)位置的值

    這篇文章主要介紹了Java如何交換字符串中兩個(gè)位置的值問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • 基于python實(shí)現(xiàn)檢索標(biāo)記敏感詞并輸出

    基于python實(shí)現(xiàn)檢索標(biāo)記敏感詞并輸出

    這篇文章主要介紹了基于python實(shí)現(xiàn)檢索敏感詞并輸出,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • Python super( )函數(shù)用法總結(jié)

    Python super( )函數(shù)用法總結(jié)

    今天給大家?guī)?lái)的知識(shí)是關(guān)于Python的相關(guān)知識(shí),文章圍繞著super( )函數(shù)展開(kāi),文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • 對(duì)json字符串與python字符串的不同之處詳解

    對(duì)json字符串與python字符串的不同之處詳解

    今天小編就為大家分享一篇對(duì)json字符串與python字符串的不同之處詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-12-12
  • django的分頁(yè)器Paginator 從django中導(dǎo)入類(lèi)

    django的分頁(yè)器Paginator 從django中導(dǎo)入類(lèi)

    這篇文章主要介紹了django的分頁(yè)器Paginator 從django中導(dǎo)入類(lèi),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • 使用python的pexpect模塊,實(shí)現(xiàn)遠(yuǎn)程免密登錄的示例

    使用python的pexpect模塊,實(shí)現(xiàn)遠(yuǎn)程免密登錄的示例

    今天小編就為大家分享一篇使用python的pexpect模塊,實(shí)現(xiàn)遠(yuǎn)程免密登錄的示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-02-02
  • Python浮點(diǎn)數(shù)取整、格式化和NaN處理的操作方法

    Python浮點(diǎn)數(shù)取整、格式化和NaN處理的操作方法

    這篇文章主要介紹了Python浮點(diǎn)數(shù)取整、格式化和NaN處理的操作方法,本文較詳細(xì)介紹了取整的三種方法,格式化浮點(diǎn)數(shù)輸出的示例代碼詳解,感興趣的朋友跟隨小編一起看看吧
    2022-05-05
  • 使用Python實(shí)現(xiàn)繪制發(fā)散條形圖

    使用Python實(shí)現(xiàn)繪制發(fā)散條形圖

    發(fā)散條形圖用于簡(jiǎn)化多個(gè)組的比較,它許我們比較各組中的數(shù)值,還幫助我們快速地想象出有利的和不利的或積極的和消極的反應(yīng),下面我們就來(lái)看看如何使用Python繪制發(fā)散條形圖吧
    2024-04-04

最新評(píng)論