2016-03-24 77 views
0

我有一些熊貓數據框,我可以使用.to_pickle()保存到磁盤。這樣的對象是200k-700k。Python Pickle佔用多少內存?

我從memcache.py in the Python-memcache github project看到,它在緩存之前先醃製對象並壓縮它們。

默認情況下,memcached只允許值高達1MB。我發現試圖緩存我的200k數據框可以正常工作,但是60萬個不會在Python memcache級別設置(客戶端甚至不會發出set命令,除非我在memcached上使用-I,並相應地爲我的Python設置memcache.SERVER_MAX_VALUE_LENGTH客戶)。

將大約100個這樣的數據幀存儲到memcache中,-I 5m允許它們全部適合,並且在寫入pickle文件的磁盤上佔用36MB(36212字節)。每memcached的stats命令,我看到幾乎3倍的字節都被寫入,

STAT bytes_read 89917017 
STAT bytes_written 89917211 
... 
STAT bytes 53022739 

它是那麼奇怪的是隻有53MB的存儲,如果89MB寫。

如果我改變我的memcaching代碼,以酸洗DataFrames 第一(即寫入與.to_pickle()一個臨時文件,讀取臨時文件存儲到內存緩存),我看到每個內存緩存stats數據大小匹配什麼是磁盤上時,我店相同的文件。

STAT bytes_read 36892901 
STAT bytes_written 36893095 
... 
STAT bytes 36896667 

用於存儲酸洗對象的內存與其在磁盤上的大小相比的比例是多少?爲什麼python memcache不能像使用.to_pickle()一樣將DataFrames轉換爲更小的pickle大小呢?

+0

Pickle可能不是存儲DataFrame的最佳選擇。爲什麼不把它們存儲爲CSV或其他更廣泛使用的格式? – BrenBarn

+0

我花了一些時間探索。我會在下面回答我自己的問題。以CSV格式存儲(奇怪)幾乎與二進制酸洗一樣小。 – hamx0r

+0

您對導出格式有什麼目標/要求?如果你希望它很小,你最好使用像msgpack這樣的格式。根據你的自我回答,目前還不清楚你爲什麼使用泡菜。 – BrenBarn

回答

0

似乎python-memcache使用ASCII編碼時,泡菜的對象,而大熊貓的to_pickle()使用泡菜V2在二進制編碼這是較小的。如果我按照@ BrenBarn的建議將我的數據框導出爲CSV,我會得到比二進制數據框略大的文件,但仍然是ASCII pickle數據框的大小的1/3。

我的解決方法,用大熊貓做二進制酸洗memcaching是這樣的(我還添加了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的這種用法在寫入磁盤時會減慢速度,但測試表明它的速度是將磁盤存儲到磁盤並從那裏加載它的兩倍。

查看python-memcached的代碼,我發現可以使用set(min_compress_len=X)觸發python-memcache在設置它們之前壓縮值。使用這種方法將內存降低到我的預酸洗技巧的40%。

最後,python-memcached構造函數採用pickleProtocol ARG其中,如果設置爲2,將使用相同的酸洗協議熊貓to_pickle()一樣。

pickleProtocol=2min_compress_len=1(始終導致壓縮)相結合導致的內存使用量約爲單獨使用二進制酸洗時的25%,壓縮開銷增加了運行時間約13%,以將所有數據幀寫入內存緩存。