我正在开发一个非常积极的缓存的网络应用程序。几乎Web应用程序的每个组件:视图,部分视图,控制器输出,磁盘加载,REST-API调用,数据库查询。可以缓存的任何级别的所有内容都被缓存,所有这些都使用装饰器。
当然,这是非常快速的,因为绝大多数HTML生成都包含纯函数,而磁盘/ REST API的负载非常少。此外,我执行的少量磁盘加载/数据库查询/ REST API查询也会被缓存,直到失效,因此除非只是更改,否则它们也非常快。
所以一切都很快,但有一个障碍:所有这些东西都被缓存在内存中,在我的WSGI进程中的一个巨大的全局字典中,因此可以直接存储而无需序列化。一旦我开始在memcached中放入内容,缓存命中所花费的时间不会发生太大变化,但是将内容放入缓存会花费更长的时间。一般来说没关系,但是每个页面的初始“填充缓存”生成从~900ms(考虑到从磁盘读取多少平面文件已经非常快)到大约~9000ms。作为参考,一旦缓存预热,生成任意页面需要10ms。
分析代码,绝大部分时间都是cPickle。所以问题是,我怎样才能让它更快?是否有任何内存缓存,我可以直接将我的对象传递给没有序列化?或者某种方式可以更快地缓存我的大堆物体?我可以在没有持久性memcached的情况下使用,但随后我的性能(或缺乏性能)将成为Apache / WSGI流程管理器的一时兴起。
答案 0 :(得分:3)
如果您要序列化Python对象而不是简单数据类型,并且 要使用pickle,请尝试cPickle.HIGHEST_PROTOCOL:
my_serialized_object = cPickle.dumps(my_object, cPickle.HIGHEST_PROTOCOL)
默认协议与旧版本的Python兼容,但您可能并不关心。
我只是使用1000键dict做了一个简单的基准测试,它的速度几乎快了几个数量级。
更新:由于您似乎已经在使用最高协议,因此您将不得不做一些额外的工作以获得更高的性能。以下是我现在要做的事情:
确定哪些类是最慢的腌制
在类中创建一对方法以实现更快的序列化方法,比如_to_string()和_from_string(s)。实际的序列化可以根据对象所包含的内容以及如何使用它来定制。例如,某些对象实际上可能只包含一个简单的字符串,例如呈现的模板,有些可能实际上是作为JSON发送到浏览器,在这种情况下,您可以简单地序列化为JSON并直接提供它。使用timeit module确保您的方法实际上更快
在装饰器中,检查hasattr(object,'_ to_string')并使用它,如果它存在
此方法允许您首先处理最差的类,并对代码库引入最小的中断。