我有一些pandas DataFrames,我可以使用.to_pickle()
保存到磁盘。这样的物体是200k-700k。
我从memcache.py in the Python-memcache github project看到,它在缓存之前腌制对象并压缩它们。
默认情况下,memcached仅允许最大1MB的值。我发现尝试缓存我的200k DataFrames工作正常,但600k的那些没有设置在Python内存缓存级别(客户端甚至不发出set命令,除非我在memcached上使用-I
并设置{ {1}}因此我的Python客户端)。
将大约100个这样的数据帧存储到带有memcache.SERVER_MAX_VALUE_LENGTH
的内存缓存中,这使得它们全部适合并在磁盘上占用36MB(36212字节)并带有写入的pickle文件。根据memcached -I 5m
命令,我看到写入了近3倍的字节,
stats
奇怪的是,如果写入89MB,则只能存储53MB。
如果我改变我的memcaching代码以首先挑选DataFrames (即用STAT bytes_read 89917017
STAT bytes_written 89917211
...
STAT bytes 53022739
写入临时文件,请读取该临时文件以存储到memcache),我看到每个memcache的数据大小.to_pickle()
匹配存储相同文件时磁盘上的内容。
stats
用于存储pickle对象的内存与磁盘上的大小比例是多少?为什么python memcache不能像使用STAT bytes_read 36892901
STAT bytes_written 36893095
...
STAT bytes 36896667
一样将DataFrames转换为更小的pickle大小呢?
答案 0 :(得分:0)
似乎python-memcache
在腌制对象时使用ASCII编码,而pandas'to_pickle()
在二进制编码中使用较小的pickle v2。如果按照@BrenBarn的建议将我的数据帧导出为CSV,我会得到比二进制数据帧略大的文件,但仍然是ASCII-pickled数据帧大小的1/3。
我使用Pandas在memcaching之前进行二进制酸洗的解决方法是这样的(我还添加了namespace
与Google App Engine非常相似,以帮助确保在为不同的应用程序使用相同的memcache时的密钥唯一性:/ p>
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存储到磁盘并从那里加载它们的速度的2倍。
查看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%是时候把我所有的数据帧写到memcache了。