2010-07-30 21 views
6

Tôi đang đấu tranh rò rỉ bộ nhớ trong một dự án Python và đã dành nhiều thời gian cho nó. Tôi đã suy luận vấn đề với một ví dụ nhỏ. Bây giờ có vẻ như tôi biết giải pháp, nhưng tôi không thể hiểu được lý do tại sao.Tại sao việc chuyển nhượng danh sách lệnh python ăn bộ nhớ?

import random 

def main(): 
    d = {} 
    used_keys = [] 
    n = 0 
    while True: 
     # choose a key unique enough among used previously 
     key = random.randint(0, 2 ** 60) 
     d[key] = 1234 # the value doesn't matter 
     used_keys.append(key) 
     n += 1 
     if n % 1000 == 0: 
      # clean up every 1000 iterations 
      print 'thousand' 
      for key in used_keys: 
       del d[key] 
       used_keys[:] = [] 
       #used_keys = [] 

if __name__ == '__main__': 
    main() 

Ý tưởng là tôi lưu trữ một số giá trị trong dict d và ghi nhớ các phím được sử dụng trong một danh sách để có thể làm sạch dict bất cứ lúc nào.

Biến thể này của chương trình tự tin ăn bộ nhớ không bao giờ trả lại bộ nhớ. Nếu tôi sử dụng phương pháp thay thế để „xóa” used_keys được nhận xét trong ví dụ, tất cả đều ổn: mức tiêu thụ bộ nhớ vẫn ở mức không đổi.

Tại sao?

Thử nghiệm trên CPython và nhiều linux.

+0

Làm thế nào để bạn biết chắc chắn nó không bao giờ trả về? Nó có thể chỉ là hệ điều hành không bao giờ yêu cầu nó trở lại. – detly

+2

Không nên xóa 'used_keys' nằm ngoài vòng lặp' for key in used_keys'? – adamk

+2

> Ý tưởng là tôi lưu trữ một số giá trị trong dict d và ghi nhớ các phím đã sử dụng trong danh sách để có thể làm sạch dict theo thời gian. Tại sao không sử dụng 'd.keys()'? Nó sẽ là cùng một danh sách các phím. –

Trả lời

5

Đây là lý do - phương pháp hiện tại không xóa các khóa khỏi dict (chỉ một thực tế). Điều này là do bạn xóa danh sách used_keys trong vòng lặp và vòng lặp thoát sớm.

Phương pháp thứ 2 (nhận xét), tuy nhiên, không hoạt động khi bạn gán một giá trị mới cho used_keys để vòng lặp kết thúc thành công.

Thấy sự khác biệt giữa:

>>> a=[1,2,3] 
>>> for x in a: 
... print x 
... a=[] 
... 
1 
2 
3 

>>> a=[1,2,3] 
>>> for x in a: 
... print x 
... a[:] = [] 
... 
1 
>>> 
+1

Ah !! Tôi ngu ngốc, ngu ngốc, ngu ngốc. Tôi đã rất hạnh phúc để tái tạo lại sự rò rỉ bộ nhớ trong một đoạn nhỏ ... Tất nhiên là một sai lầm đáng buồn. Nó không đại diện cho vấn đề của tôi, tôi sẽ tiếp tục săn bắn. Nhưng bạn đúng với câu trả lời về câu hỏi ban đầu. Cảm ơn! – nkrkv

0

Tại sao không phải cái gì muốn làm việc này?

from itertools import count 
import uuid 

def main(): 
    d = {} 
    for n in count(1): 
     # choose a key unique enough among used previously 
     key = uuid.uuid1() 
     d[key] = 1234 # the value doesn't matter 
     if n % 1000 == 0: 
      # clean up every 1000 iterations 
      print 'thousand' 
      d.clear() 

if __name__ == '__main__': 
    main() 
Các vấn đề liên quan