2014-04-10 17 views
8

RAM cần thiết để lưu trữ dữ liệu trong bộ nhớ so với dung lượng đĩa cần thiết để lưu trữ cùng một dữ liệu trong một tệp như thế nào? Hay là không có sự tương quan tổng quát?Kích thước dữ liệu trong bộ nhớ so với đĩa

Ví dụ: giả sử tôi chỉ có một tỷ giá trị dấu phẩy động. Được lưu trữ dưới dạng nhị phân, có thể là 4 tỷ byte hoặc 3.7 GB trên đĩa (không bao gồm tiêu đề và các phần tử như vậy). Sau đó, nói rằng tôi đọc những giá trị vào một danh sách trong Python ... bao nhiêu RAM tôi nên mong đợi rằng để yêu cầu?

+0

RAM khác! Có danh sách trên không, trong số những thứ khác. Nếu bạn lo lắng, a) tìm hiểu và b) xem xét việc lưu trữ dữ liệu thô trong bộ nhớ và giải nén dữ liệu đó một cách nhanh chóng (nó phụ thuộc vào những gì bạn đang làm với nó). – Ryan

+2

Liên quan: http: // stackoverflow.com/a/994010/846892 –

+0

Suy nghĩ đầu tiên của tôi là mất một lúc để người dùng đợi cho đến khi tất cả dữ liệu đó được tải vào RAM. –

Trả lời

3

Python Object Dữ liệu Kích cỡ

Nếu dữ liệu được lưu trữ trong một số đối tượng python, sẽ có nhiều hơn một chút dữ liệu gắn liền với các dữ liệu thực tế trong bộ nhớ.

Điều này có thể dễ dàng được kiểm tra.

The size of data in various forms

Thật thú vị khi lưu ý như thế nào, lúc đầu, các chi phí của đối tượng python rất có ý nghĩa đối với dữ liệu nhỏ, nhưng nhanh chóng trở nên không đáng kể.

Đây là mã ipython sử dụng để tạo ra các âm mưu

%matplotlib inline 
import random 
import sys 
import array 
import matplotlib.pyplot as plt 

max_doubles = 10000 

raw_size = [] 
array_size = [] 
string_size = [] 
list_size = [] 
set_size = [] 
tuple_size = [] 
size_range = range(max_doubles) 

# test double size 
for n in size_range: 
    double_array = array.array('d', [random.random() for _ in xrange(n)]) 
    double_string = double_array.tostring() 
    double_list = double_array.tolist() 
    double_set = set(double_list) 
    double_tuple = tuple(double_list) 

    raw_size.append(double_array.buffer_info()[1] * double_array.itemsize) 
    array_size.append(sys.getsizeof(double_array)) 
    string_size.append(sys.getsizeof(double_string)) 
    list_size.append(sys.getsizeof(double_list)) 
    set_size.append(sys.getsizeof(double_set)) 
    tuple_size.append(sys.getsizeof(double_tuple)) 

# display 
plt.figure(figsize=(10,8)) 
plt.title('The size of data in various forms', fontsize=20) 
plt.xlabel('Data Size (double, 8 bytes)', fontsize=15) 
plt.ylabel('Memory Size (bytes)', fontsize=15) 
plt.loglog(
    size_range, raw_size, 
    size_range, array_size, 
    size_range, string_size, 
    size_range, list_size, 
    size_range, set_size, 
    size_range, tuple_size 
) 
plt.legend(['Raw (Disk)', 'Array', 'String', 'List', 'Set', 'Tuple'], fontsize=15, loc='best') 
+1

Câu trả lời này không chính xác. Tài liệu cho sys.getsizeof nói rằng "Chỉ tiêu thụ bộ nhớ trực tiếp được gán cho đối tượng được tính, không phải là mức tiêu thụ bộ nhớ của các đối tượng mà nó đề cập đến." Vì vậy, bạn chỉ chiếm bộ nhớ được phân bổ trong các thùng chứa và không xem xét bộ nhớ bổ sung được phân bổ cho chính các đối tượng số. –

+1

Bạn có đề xuất về cách xác định phân bổ bộ nhớ đầy đủ không? Tôi sẽ làm lại âm mưu! – tmthydvnprt

+0

Tôi nghĩ rằng bạn cần thêm 'len (double_list) * sys.getsizeof (1.0)' vào kích thước bộ nhớ được báo cáo cho 'list',' set' và 'tuple'. Có lẽ một số bộ nhớ bổ sung cần thiết để quản lý phân bổ, nhưng tôi không biết làm thế nào để đo nó và nó sẽ là không đáng kể. –

1

Trong một danh sách Python đơn giản, mỗi số tăng gấp đôi độ chính xác đòi hỏi ít nhất 32 byte của bộ nhớ, nhưng chỉ có 8 byte được sử dụng để lưu trữ thực tế số, phần còn lại là cần thiết để hỗ trợ tính chất động của Python.

Đối tượng phao được sử dụng trong CPython được định nghĩa trong floatobject.h:

typedef struct { 
    PyObject_HEAD 
    double ob_fval; 
} PyFloatObject; 

nơi PyObject_HEADa macro that expands đến PyObject struct:

typedef struct _object { 
    Py_ssize_t ob_refcnt; 
    struct _typeobject *ob_type; 
} PyObject; 

Do đó, mọi đối tượng dấu chấm động trong các cửa hàng Python hai pointer- các trường có kích thước (vì vậy mỗi trường có 8 byte trên kiến ​​trúc 64 bit) bên cạnh 8 byte, cho 24 byte bộ nhớ phân bổ trên mỗi số. Điều này được xác nhận bởi sys.getsizeof(1.0) == 24.

Điều này có nghĩa rằng một danh sách các n đôi bằng Python mất ít nhất 8*n byte của bộ nhớ chỉ để lưu trữ các con trỏ (PyObject*) để các đối tượng số, và mỗi đối tượng số đòi hỏi thêm 24 byte. Để kiểm tra nó, hãy thử chạy những dòng sau trong Python REPL:

>>> import math 
>>> list_of_doubles = [math.sin(x) for x in range(10*1000*1000)] 

và xem cách sử dụng bộ nhớ của trình thông dịch Python (tôi đã nhận khoảng 350 MB bộ nhớ được phân bổ trên máy tính x86-64 của tôi). Lưu ý rằng nếu bạn đã cố gắng:

>>> list_of_doubles = [1.0 for __ in range(10*1000*1000)] 

bạn sẽ có được chỉ khoảng 80 MB, bởi vì tất cả các yếu tố trong danh sách tham khảo các cùng dụ của điểm số nổi 1.0.

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