[英]How much memory does a Python Pickle take?
我有一些pandas DataFrames,可以使用.to_pickle()
保存到磁盘。 这样的对象是200k-700k。
我从Python-memcache github项目中的memcache.py中看到,它腌制对象并在缓存之前对其进行压缩。
默认情况下,memcached仅允许最大1MB的值。 我发现尝试缓存我的200k DataFrames可以正常工作,但是600k的DataFrame没有在Python内存缓存级别设置(除非我在memcached上使用-I
并相应地设置memcache.SERVER_MAX_VALUE_LENGTH
,否则客户端甚至不会发出set命令为我的Python客户端)。
使用-I 5m
将大约100个这样的数据帧存储到内存缓存中,它们全部都可以容纳,并且在写入了腌制文件的磁盘上占用36MB(36212字节)。 根据memcached stats
命令,我看到写入的字节几乎是原来的3倍,
STAT bytes_read 89917017
STAT bytes_written 89917211
...
STAT bytes 53022739
那么奇怪的是,如果写入89MB,则仅存储53MB。
如果我更改内存管理代码以首先对DataFrame进行酸洗(即使用.to_pickle()
写入临时文件,读取该临时文件以存储到内存缓存),则当我存储相同文件时,我会看到每个内存缓存stats
的数据大小与磁盘上的内容匹配。
STAT bytes_read 36892901
STAT bytes_written 36893095
...
STAT bytes 36896667
相较于其在磁盘上的大小,用于存储腌制对象的内存比例是多少? 并且为什么python memcache不会像使用.to_pickle()
一样,将DataFrames转换为较小的泡菜尺寸,执行类似的有效工作?
似乎python-memcache
在对对象进行腌制时会使用ASCII编码,而pandas的to_pickle()
在较小的二进制编码中使用pickle v2。 如果我按照@BrenBarn的建议将数据帧导出为CSV,我会得到比二进制数据帧稍大的文件,但仍约为ASCII腌制数据帧的1/3。
我的解决方法是,在使用memcaching之前使用Pandas进行二进制腌制(我还像Google App Engine一样添加了namespace
arg,以确保在为不同的应用程序使用相同的内存缓存时确保键唯一性):
import memcache
import tempfile
import pandas as pd
mc_client = memcache.Client(['localhost:11211'], debug=0)
def mc_get(key, namespace):
""" Gets pickle from Memecache and converts to a dataframe
"""
data = mc_client.get('{}_{}'.format(namespace, key))
if data is None:
return
temp_file = tempfile.NamedTemporaryFile()
temp_file.write(data)
temp_file.flush()
return pd.read_pickle(temp_file.name)
def mc_set(key, df, namespace):
""" Convert dataframe to dict and store it to memcache
"""
temp_file = tempfile.NamedTemporaryFile()
df.to_pickle(temp_file.name)
temp_file.flush()
data = temp_file.read()
mc_client.set('{}_{}'.format(namespace, key), data)
看起来,使用tempfile会将它写入磁盘时会减慢速度,但是测试表明,将pickle文件存储到磁盘并从那里加载它们的速度是其两倍。
查看python-memcached代码,我发现可以使用set(min_compress_len=X)
触发python-memcache
在设置值之前对其进行压缩。 使用这种方法将内存减少到我的预浸技巧的40%。
最后, python-memcached
构造函数采用pickleProtocol
arg,如果将其设置为2
,则将使用与Pandas的to_pickle()
相同的酸洗协议。
将pickleProtocol=2
与min_compress_len=1
结合在一起(总是导致压缩)导致内存使用量大约是单独使用二进制酸洗的25%,并且压缩的开销将运行时间增加了约13%,从而将所有数据帧写入记忆快取。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.