在内存中存储数据所需的RAM与在文件中存储相同数据所需的磁盘空间相比如何?或者没有广义相关性?
例如,假设我只有十亿个浮点值。以二进制形式存储,磁盘上有40亿字节或3.7GB(不包括标题等)。然后说我将这些值读入Python的列表中......我应该要求多少RAM?
答案 0 :(得分:5)
如果数据存储在某个python对象中,则会有更多数据附加到内存中的实际数据中。
这可能很容易测试。
值得注意的是,首先,python对象的开销对于小数据是多么重要,但很快就会变得微不足道。
以下是用于生成情节的iPython代码
%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 :(得分:1)
在普通的Python列表中,每个双精度数字需要至少32个字节的内存,但只有8个字节用于存储实际数字,其余部分用于支持Python的动态特性。
CPython中使用的float对象在floatobject.h中定义:
typedef struct {
PyObject_HEAD
double ob_fval;
} PyFloatObject;
其中PyObject_HEAD
PyObject
为typedef struct _object {
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
} PyObject;
结构:
sys.getsizeof(1.0) == 24
因此,Python中的每个浮点对象都存储两个指针大小的字段(因此每个字节在64位体系结构上占用8个字节),而不是8字节的双字节,每个数字给出24个字节的堆分配内存。这由n
确认。
这意味着Python中的8*n
双精度列表至少需要PyObject*
个字节的内存才能将指针(>>> import math
>>> list_of_doubles = [math.sin(x) for x in range(10*1000*1000)]
)存储到该数字中对象,每个数字对象需要额外的24个字节。要测试它,请尝试在Python REPL中运行以下行:
>>> list_of_doubles = [1.0 for __ in range(10*1000*1000)]
并查看Python解释器的内存使用情况(我在x86-64计算机上获得了大约350 MB的已分配内存)。请注意,如果您尝试:
1.0
您将获得大约80 MB,因为列表中的所有元素都引用浮点数<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false"
android:drawable="@drawable/list_item_disabled"/>
<item
android:drawable="@drawable/list_item_normal"/>
</selector>
的相同实例。