2012-11-10 38 views
7

Tôi hiểu rằng del d[key] sẽ xóa cặp khóa-giá trị, trong khi d[key]=None chỉ không tham chiếu giá trị.Mức tiêu thụ bộ nhớ của từ điển: đặt giá trị Không so với xóa mục

Tuy nhiên, về quản lý bộ nhớ, có sự khác biệt nào không? Không đặt giá trị ngay lập tức cho bộ sưu tập rác kích hoạt None, giả sử rằng không có biến nào khác tham chiếu giá trị này?

Tôi chạy một chút thí nghiệm:

In [74]: import sys 
In [75]: a = {'a': 'blah'} 

In [76]: sys.getsizeof(a) 
Out[76]: 280 

In [77]: a['a'] = None 

In [79]: sys.getsizeof(a) 
Out[79]: 280 

In [80]: del a['a'] 

In [81]: sys.getsizeof(a) 
Out[81]: 280 

Không chắc chắn nếu phương pháp này là hợp lệ, nhưng có vẻ như không có sự khác biệt về kích thước của từ điển ở tất cả. Tôi phải bỏ lỡ một cái gì đó ở đây.

+6

Có giá trị '' None'' vẫn có nghĩa là từ điển phải có tham chiếu đến khóa được liên kết với tham chiếu đến '' None'', việc xóa giá trị sẽ xóa nó khỏi dict hoàn toàn. Chúng là các hoạt động hoàn toàn khác nhau và không tương đương với nhau. –

+1

Một đối tượng 'dict' bao gồm' smalltable' cho tối đa 5 mục (có kích thước cho 8 mục, nhưng nó chỉ có thể là 2/3 đầy đủ). Bảng phát triển trong quyền hạn của 2, bắt đầu từ 8. Trên một hệ thống 32-bit một 'PyDictEntry' là 12 byte, do đó,' smalltable' là 96 byte, cộng với 28 byte trong lĩnh vực othe, đến 124 byte. 'sys.getizeof' cũng báo cáo 12 byte được thêm vào dict để theo dõi GC ('gc_next',' gc_prev', 'gc_refs'), tạo tổng kích thước 136 byte. GC xử lý các chu kỳ tham chiếu có thể ngăn chặn các vùng chứa không thể truy cập (ví dụ: các dicts, classes) khỏi bị deallocated. – eryksun

+1

@Lattyware: OP không nói rằng chúng tương đương nhau, anh ta nói rằng 'd [key] = None' không tham chiếu giá trị, điều này đúng. –

Trả lời

9

sys.getsizeof đo kích thước của chính dict; không phải kích thước của các giá trị chứa trong đó.

None là một đối tượng. Nó đòi hỏi một số bộ nhớ.

Để tìm kích thước của một dict bao gồm kích thước của các giá trị mà nó chứa, bạn có thể sử dụng pympler:

In [26]: import pympler.asizeof as asizeof 

In [27]: asizeof.asizeof({'a': None}) 
Out[27]: 168 

In [28]: asizeof.asizeof({}) 
Out[28]: 136 

In [29]: import sys 

In [30]: 
In [31]: sys.getsizeof({}) 
Out[31]: 136 

In [34]: sys.getsizeof({'a':None}) 
Out[34]: 136 
+0

cảm ơn! Nhưng điều đó sẽ xóa bộ nhớ nhanh hơn 'del' hoặc đặt giá trị thành' None'? Hoặc câu hỏi đó phụ thuộc vào một số yếu tố khác? – MLister

+0

"Không có đối tượng nào. Nó đòi hỏi một số bộ nhớ." Trên thực tế, Không có một singleton, do đó, nó không yêu cầu bộ nhớ chính nó. Có nó trong một từ điển không yêu cầu bộ nhớ (cho khóa và cho con trỏ). –

+0

@MLister Khi tham chiếu Python được tính, cả hai sẽ có tác dụng tương tự khi tham chiếu bị mất (hoặc bằng cách xóa khóa và giá trị, hoặc thay đổi giá trị thành giá trị khác), nếu số tham chiếu đạt 0, bộ thu gom rác sẽ xóa ký ức. –

2

unutbu là đúng. Nhưng cũng có thể thu gom rác python có thể hơi chậm trên sự hấp thu đôi khi.

Gọi del trên một đối tượng và loại bỏ tất cả các tham chiếu đến đối tượng đó có nghĩa là người thu gom rác có thể thu thập bất cứ khi nào nó cảm thấy sẵn sàng. Điều này thường sẽ không làm giảm số lượng bộ nhớ được sử dụng ngay lập tức.

bạn có thể sử dụng mô-đun gc để bắt buộc thu thập và xem những gì người thu gom rác thực sự thấy.

+2

Bộ thu gom rác của CPython là tài liệu tham khảo được tính, vì vậy theo phiên bản Python phổ biến nhất, nó sẽ giải phóng bộ nhớ rất nhanh chóng. –

+0

@Lattyware: cảm ơn +1 – Sheena

+0

'gc.collect (generation = 2)' có thể xóa các vùng chứa bị kẹt trong các chu trình tham chiếu (ví dụ 'ab, ba = b, a'), nhưng chỉ khi chúng không có một '__del__' finalizer. Nếu bạn sử dụng 'generation = 2', nó cũng xóa' freelist 'được sử dụng bởi PyFrame, PyMethod, PyCFunction, PyTuple, PyUnicode, PyInt và PyFloat. Đây là danh sách các đối tượng được cấp phát có thể được sử dụng lại mà không phải phân bổ một đối tượng mới trên heap. Trừ khi bạn hoàn toàn cần bộ nhớ trở lại từ những người tự do, sử dụng 'gc.collect (1)'. – eryksun

0

Từ điển python chứa, bên cạnh logic, con trỏ tới tất cả các khóa và con trỏ đến tất cả các giá trị.

  • Đặt giá trị thành Không để nguyên số đối tượng trong từ điển còn nguyên, nó thay thế một con trỏ giá trị thành con trỏ đến đối tượng Không có. Nếu đối tượng giá trị cũ không còn được tham chiếu từ nơi khác, nó sẽ bị thu gom rác. Chìa khóa sẽ ở lại.
  • Xóa giá trị, nếu điều đó có nghĩa là khóa và/hoặc giá trị không còn được tham chiếu nữa, sẽ dẫn đến việc xóa cả hai và về nguyên tắc làm giảm kích thước của từ điển. Cho dù từ điển sẽ thực sự "thu nhỏ" là một chi tiết thực hiện tôi không biết.

Thử nghiệm điều này trên một đối tượng có thể không đại diện. Hãy thử một triệu. Hơn nữa, thử nghiệm nó với một đối tượng "string" ngắn có thể không đại diện, bởi vì một chuỗi có thể được "interned", tức là nó có thể trở thành một phần của bộ các đối tượng không thể tái cấu trúc được tái sử dụng tự động bất cứ khi nào người thông dịch cần lại.

Các vấn đề liên quan