Tôi đang làm việc trên một dự án có liên quan đến việc truy cập dữ liệu từ danh sách lớn được lưu trong bộ nhớ. Bởi vì danh sách này khá là đồ sộ (hàng triệu dòng) nên tôi để mắt đến lượng bộ nhớ đang được sử dụng. Tôi sử dụng OS X để tôi tiếp tục mở Activity Monitor khi tạo các danh sách này.Danh sách Python sử dụng bộ nhớ bất thường
Tôi đã nhận thấy rằng lượng bộ nhớ được sử dụng bởi danh sách có thể khác nhau tùy thuộc vào cách nó được xây dựng nhưng tôi dường như không thể hiểu tại sao.
Bây giờ đối với một số mã ví dụ:
(Tôi đang sử dụng Python 2.7.4 trên OSX 10.8.3)
Chức năng đầu tiên dưới đây tạo ra một danh sách và điền nó với tất cả cùng ba số ngẫu nhiên.
Hàm thứ hai bên dưới tạo danh sách và điền nó với tất cả các số ngẫu nhiên khác nhau.
import random
import sys
def make_table1(size):
list1 = size *[(float(),float(),float())] # initialize the list
line = (random.random(),
random.random(),
random.random())
for count in xrange(0, size): # Now fill it
list1[count] = line
return list1
def make_table2(size):
list1 = size *[(float(),float(),float())] # initialize the list
for count in xrange(0, size): # Now fill it
list1[count] = (random.random(),
random.random(),
random.random())
return list1
(Trước tiên cho tôi nói rằng tôi nhận ra đoạn mã trên có thể được viết hiệu quả hơn nhiều. Nó được viết theo cách này để giữ cho hai ví dụ như tương tự càng tốt.)
Bây giờ tôi có thể tạo một số danh sách sử dụng các chức năng này:
In [2]: thing1 = make_table1(6000000)
In [3]: sys.getsizeof(thing1)
Out[3]: 48000072
Tại thời điểm này, bộ nhớ của tôi đã sử dụng nhảy khoảng 46 MB, đó là những gì tôi mong đợi từ thông tin được đưa ra ở trên.
Bây giờ cho các chức năng sau:
In [4]: thing2 = make_table2(6000000)
In [5]: sys.getsizeof(thing2)
Out[5]: 48000072
Như bạn thấy, bộ nhớ đưa lên bởi hai danh sách là như nhau. Chúng có cùng độ dài như vậy, điều đó được mong đợi. Những gì tôi đã không mong đợi là bộ nhớ của tôi được sử dụng như được đưa ra bởi Activity Monitor nhảy đến hơn 1 GB!
Tôi hiểu rằng sẽ có một số chi phí nhưng cao hơn 20x? 1 GB cho danh sách 46MB?
Nghiêm túc?
Được rồi, vào chẩn đoán ...
Điều đầu tiên tôi đã cố gắng là để thu thập bất kỳ rác:
In [5]: import gc
In [6]: gc.collect()
Out[6]: 0
Nó làm không khác biệt với dung lượng bộ nhớ sử dụng.
Tiếp theo, tôi sử dụng cá bảy màu để xem nơi bộ nhớ đang diễn ra:
In [7]: from guppy import hpy
In [8]: hpy().heap()
Out[8]:
Partition of a set of 24217689 objects. Total size = 1039012560 bytes.
Index Count % Size % Cumulative % Kind (class/dict of class)
0 6054789 25 484821768 47 484821768 47 tuple
1 18008261 74 432198264 42 917020032 88 float
2 2267 0 96847576 9 1013867608 98 list
3 99032 0 11392880 1 1025260488 99 str
4 585 0 1963224 0 1027223712 99 dict of module
5 1712 0 1799552 0 1029023264 99 dict (no owner)
6 13606 0 1741568 0 1030764832 99 types.CodeType
7 13355 0 1602600 0 1032367432 99 function
8 1494 0 1348088 0 1033715520 99 type
9 1494 0 1300752 0 1035016272 100 dict of type
<691 more rows. Type e.g. '_.more' to view.>
okay, bộ nhớ của tôi được đưa lên bởi:
462 MB của tuple (huh?)
412 MB phao (cái gì?)
92 MB danh sách (Được rồi, cái này có ý nghĩa. 2 * 46MB = 92)
Danh sách của tôi được preallocated vì vậy tôi không nghĩ rằng có quá phân bổ đang xảy ra.
Câu hỏi:
Tại sao dung lượng bộ nhớ được sử dụng bởi hai danh sách này rất khác nhau?
Có cách nào khác để điền danh sách không có quá nhiều chi phí không?
Có cách nào giải phóng tất cả bộ nhớ đó không?
Lưu ý: Vui lòng không đề xuất lưu trữ trên đĩa hoặc sử dụng cấu trúc dữ liệu array.array hoặc sumpy hoặc gấu trúc. Đó là tất cả những lựa chọn tuyệt vời nhưng câu hỏi này không phải là về chúng. Câu hỏi này là về các danh sách cũ đơn giản.
Tôi đã thử mã tương tự với Python 3.3 và kết quả giống nhau.
Đây là người có số similar problem. Nó chứa một số gợi ý nhưng nó không phải là cùng một câu hỏi.
Cảm ơn tất cả!
bạn dường như có lợi ích trong một mảng 2ngày kích thước 6000000 x 3; Bạn đã xem xét gumpy (ví dụ: 'numpy.random.rand (6000000, 3)') – SingleNegationElimination