2016-02-12 76 views
2

我曾经在全局变量中缓存数据库查询以加速我的应用程序。由于这是强烈unadvised(并且它产生了问题),我想要使用任何类型的Django缓存。我尝试了LocMemCache和DatabaseCache,但都采取...约15秒设置我的变量(比生成数据所需的时间长两倍,即7MB大小)。写入Django缓存的速度非常慢

这是预期的吗?难道我做错了什么 ?

(Memcached限制为1MB,我不能分割我的数据,它包含任意大的二进制掩码)。

编辑:FileBasedCache也需要30秒才能设置。

Settings.py:

CACHES = { 
    'default': {...}, 
    'stats': { 
     'BACKEND': 'django.core.cache.backends.db.DatabaseCache', 
     # or 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', 
     'LOCATION': 'stats', 
    }, 
} 

Service.py:

from django.core.cache import caches 

def stats_service(): 
    stats_cache = caches['stats'] 
    if stats_cache.get('key') is None: 
     stats_cache.set('key', data) # 15s with DatabaseCache, 30s with LocMemCache 
    return stats_cache.get('key') 

全局变量(超快速)版本:

_cache = {} 

def stats_service(): 
    if _cache.get('key') is None: 
     _cache['key'] = data 
    return _cache['key'] 
+1

缓存pickles的价值,我并不感到惊讶,需要如此长的时间来腌制一个7MB的值。根据你缓存的内容和你使用的内容,可能有更好的方法。 – knbk

+0

这确实解释了,我完全错过了这一点。我绝对不想腌它(显然7MB内存不是问题)。我缓存位掩码(二进制numpy数组),我在每次计算中都重用。你有什么建议吗? – JulienD

+0

我发现这个:https://djangosnippets.org/snippets/2396/。我唯一担心的是全局字典是我在使用缓存数组的计算中使用多处理。 – JulienD

回答

2

一种选项可使用diskcache.DjangoCacheDiskCache扩展了Django缓存API以支持按原样写入和读取二进制流(避免酸洗)。对于大数值(比如大于1MB的数值)它特别有效。 DiskCache是​​一个Apache2许可磁盘,用纯Python编写,并且与Django兼容。

就你而言,你可以使用ndarray tostring和numpy fromstring方法快速转换为/从Python字符串。然后用io.StringIO包装字符串以在缓存中存储/检索。例如:

from django.core.cache import cache 

value = cache.get('cache-key', read=True) 

if value: 
    data = numpy.fromstring(value.read()) 
    value.close() 
else: 
    data = ... # Generate 7MB array. 
    cachge.set('cache-key', io.StringIO(data.tostring()), read=True) 

DiskCache延伸通过允许被存储在磁盘上的二进制块类文件值Django的缓存API。 Django cache benchmarks页面讨论并比较了备用缓存后端。

+0

谢谢,我一定会试试这个。我真的想使用快速内存​​访问而不是磁盘,并避免转换,但( – JulienD

+0

@muraveill为避免使用磁盘上的文件,请增加'large_value_threshold'设置([API文档](http://www.grantjenks。 com/docs/diskcache/api.html#diskcache.DEFAULT_SETTINGS))。高速缓存写入仍然会保留在磁盘上,但是读取会从同步的内存映射文件中发生,在这种情况下,不要用'io.StringIO'只传递原始字节字符串,不会被腌制,您可能还需要增加其他缓存设置以使用更多内存。 – GrantJ