Data size in memory vs. on disk
与在文件中存储相同数据所需的磁盘空间相比,在内存中存储数据所需的RAM如何?或者没有普遍的相关性?
例如,假设我只有十亿个浮点值。以二进制形式存储,即40亿字节或磁盘上的3.7GB(不包括头文件等)。然后假设我用python把这些值读到一个列表中…我需要多少内存?
python对象数据大小
如果数据存储在某个Python对象中,那么将有更多的数据附加到内存中的实际数据上。
这可能很容易测试。
。
有趣的是,首先要注意的是,python对象的开销对于小数据是多么的重要,但是很快就会变得微不足道。
下面是用于生成绘图的IPython代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | %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') |
在一个普通的python列表中,每个双精度数字至少需要32个字节的内存,但是只有8个字节用于存储实际的数字,其余的是支持python的动态特性所必需的。
cpython中使用的float对象在float object.h中定义:
1 2 3 4 | typedef struct { PyObject_HEAD double ob_fval; } PyFloatObject; |
号
其中,
1 2 3 4 | typedef struct _object { Py_ssize_t ob_refcnt; struct _typeobject *ob_type; } PyObject; |
因此,python中的每个浮点对象都存储两个指针大小的字段(因此每个字段在64位体系结构中占用8个字节),除了8个字节的double之外,每个数字还提供24个字节的堆分配内存。这是由
这意味着python中的
1 2 | >>> import math >>> list_of_doubles = [math.sin(x) for x in range(10*1000*1000)] |
。
查看python解释器的内存使用情况(我在x86-64计算机上获得了大约350MB的分配内存)。请注意,如果您尝试:
1 | >>> list_of_doubles = [1.0 for __ in range(10*1000*1000)] |
您将获得大约80MB,因为列表中的所有元素都引用浮点数