2011-09-27 53 views
3

我正在开发一个具有非常积极的缓存的Web应用程序。几乎Web应用程序的每个组件:视图,部分视图,控制器输出,磁盘加载,REST-API调用,数据库查询。所有可以缓存的任何级别的内容都被缓存,全部使用装饰器。Python:防止缓存放慢我的速度

当然,这个速度非常快,因为绝大多数的HTML代包含纯函数,而且很少有来自磁盘/ REST API的负载。此外,我执行的少量磁盘加载/数据库查询/ REST API查询也被缓存直到无效,所以除非只是更改,它们也非常快。因此,所有事情都很快,但有一个问题:所有这些东西都被缓存在内存中,在我的WSGI进程中的一个巨大的全局字典中,因此可以直接存储而不需要序列化。一旦我开始将东西放入memcached中,缓存命中所花费的时间不会发生太大的变化,但是将东西放入缓存开始需要更长的时间。一般来说,没关系,但每个页面的初始“填充缓存”生成时间大约为900ms(考虑到从磁盘读取多少个平面文件,这已经相当快了)约为9000ms。作为参考,一旦缓存被预热,生成一个任意页面需要10毫秒。

剖析代码,绝大多数时间都是cPickle。所以问题是,我怎样才能让这个更快?有没有任何内存缓存可以直接将我的对象传递给序列化?或者某种方式可以更快速地缓存我的大堆物体?我可以不使用持久的memcached,但是随后我的表现(或缺乏)将成为Apache/WSGI流程管理者的心血结晶。

+0

你使用cPickle协议2吗?你有没有试过[marshal](http://docs.python.org/library/marshal.html)? – jterrace

+0

我正在使用cPickle协议2.我认为元帅不适用于用户定义的类吗? –

回答

3

如果您序列化Python对象,而不是简单的数据类型,并用咸菜,尝试cPickle.HIGHEST_PROTOCOL:

my_serialized_object = cPickle.dumps(my_object, cPickle.HIGHEST_PROTOCOL) 

默认的协议与旧版本的Python兼容的,但你可能不要我不在乎。

我刚刚做了一个简单的1000基准字典的基准测试,它的速度几乎要快一个数量级。

更新:由于您似乎已经使用最高协议,您将不得不做一些额外的工作来获得更多的性能。以下是我会在这一点上做的:

  1. 确定哪些类是最慢的咸菜

  2. 创建一对类中的方法来实现更快的序列化方法,说_to_string()和_from_string(一个或多个)。实际的序列化可以根据对象的含义以及将如何使用来定制。例如,一些对象可能实际上只包含一个简单的字符串,比如一个渲染的模板,有些实际上可能会以JSON的形式发送到浏览器,在这种情况下,您可以简单地序列化为JSON并直接提供。使用timeit module以确保您的方法实际上更快

  3. 是在你的装饰,检查hasattr(对象,“_to_string”),并使用它,如果它存在

此方法可以解决最差的课程,并且对代码基础的干扰最小。

+0

元帅更快 – jterrace

+0

对于本机类型,是的,但它不支持对象,而且OP似乎暗示他正在缓存对象。 –