簡體   English   中英

在islice的發生器循環中可能存在內存泄漏

[英]Likely memory leak in generator loop with islice

我正在處理每個包含數百萬條記錄的大文件(大約2GB解壓縮,幾百MB的gzip)。

我使用islice迭代記錄,這使得我可以獲得一小部分(用於調試和開發)或者當我想測試代碼時。 我注意到我的代碼的內存使用量非常大,因此我試圖在代碼中找到內存泄漏。

下面是配對讀取中memory_profiler的輸出(我打開兩個文件並壓縮記錄),只有10 ** 5值(默認值被覆蓋)。

Line #    Mem usage    Increment   Line Contents
================================================
   137   27.488 MiB    0.000 MiB   @profile
   138                             def paired_read(read1, read2, nbrofitems = 10**8):
   139                              """ Procedure for reading both sequences and stitching them together """
   140   27.488 MiB    0.000 MiB    seqFreqs = Counter()
   141   27.488 MiB    0.000 MiB    linker_str = "~"
   142                              #for rec1, rec2 in izip(read1, read2):
   143 3013.402 MiB 2985.914 MiB    for rec1, rec2 in islice(izip(read1, read2), nbrofitems):
   144 3013.398 MiB   -0.004 MiB        rec1 = rec1[9:]                         # Trim the primer variable sequence
   145 3013.398 MiB    0.000 MiB        rec2 = rec2[:150].reverse_complement()  # Trim the low quality half of the 3' read AND take rev complement
   146                                  #aaSeq = Seq.translate(rec1 + rec2)
   147                             
   148                                  global nseqs 
   149 3013.398 MiB    0.000 MiB        nseqs += 1
   150                             
   151 3013.402 MiB    0.004 MiB        if filter_seq(rec1, direction=5) and filter_seq(rec2, direction=3):
   152 3013.395 MiB   -0.008 MiB            aakey = str(Seq.translate(rec1)) + linker_str + str(Seq.translate(rec2))
   153 3013.395 MiB    0.000 MiB            seqFreqs.update({ aakey : 1 })  
   154                                  
   155 3013.402 MiB    0.008 MiB    print "========================================"
   156 3013.402 MiB    0.000 MiB    print "# of total sequences: %d" % nseqs
   157 3013.402 MiB    0.000 MiB    print "# of filtered sequences: %d" % sum(seqFreqs.values())
   158 3013.461 MiB    0.059 MiB    print "# of repeated occurances: %d" % (sum(seqFreqs.values()) - len(list(seqFreqs)))
   159 3013.461 MiB    0.000 MiB    print "# of low-score sequences (<20): %d" % lowQSeq
   160 3013.461 MiB    0.000 MiB    print "# of sequences with stop codon: %d" % starSeqs
   161 3013.461 MiB    0.000 MiB    print "========================================"
   162 3013.504 MiB    0.043 MiB    pprint(seqFreqs.most_common(100), width = 240)

簡而言之,代碼對記錄進行了一些過濾,並跟蹤字符串在文件中出現的次數(在這種特定情況下為壓縮字符串對)。

計數器中100個字符串的150個字符和整數值應該落在100 MB的頂部,我使用@AaronHall的后續函數進行檢查

鑒於memory_profiler輸出,我懷疑islice在迭代過程中不會釋放前面的實體。 谷歌搜索讓我看到了這個錯誤報告但是它已被標記為已解決的Python 2.7,這正是我目前正在運行的。

任何意見?

編輯:我已經嘗試按照下面的評論跳過islice並使用for循環之類的

for rec in list(next(read1) for _ in xrange(10**5)):

這沒有什么顯着差異。 它是在單個文件的情況下,以避免也來自itertools izip

我的第二個故障排除想法是檢查gzip.open()讀取並將文件擴展到內存,從而導致此問題。 但是,在解壓縮文件上運行腳本沒有任何區別。

請注意,memory_profiler僅報告每行的最大內存消耗。 對於長循環,這可能會產生誤導,因為循環的第一行似乎總是報告不成比例的內存量。

這是因為它將循環的第一行與之前的行的內存消耗進行比較,這將超出循環。 這並不意味着循環的第一行消耗2985Mb,而是循環內存峰值之間的差異比循環外高2985Mb。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM