繁体   English   中英

Python Pickle需要多少内存?

[英]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=2min_compress_len=1结合在一起(总是导致压缩)导致内存使用量大约是单独使用二进制酸洗的25%,并且压缩的开销将运行时间增加了约13%,从而将所有数据帧写入记忆快取。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM