阿布云

你所需要的,不仅仅是一个好用的代理。

用Python的 __slots__ 可以节省多少空间呢

阿布云 发表于

p1.png

我们曾经提到,Oyster.com的Python web服务器怎样利用一个巨大的Python dicts(hash table),缓存大量的静态资源.我们最近在Image类中,用仅仅一行__slots__代码,让每个6G内存占用的服务进程(共4个),省出超过2G来.

这是其中一个服务器在部署代码前后的截图:

1.png

我们alloc了大约一百万个类似如下class的实例:

2.png

默认情况下,Python用一个dict来存储对象实例的属性.这在一般情况下还不错,而且非常灵活,乃至你在运行时可以随意设置新的属性.

但是,对一些在”编译”前就知道该有几个固定属性的小class来说,这个dict就有点浪费内存了.而当你把这个小浪费乘上一百万,那可就大不同了.在Python中,你可以在class中设置__slots__,它是一个包含这些固定的属性名的list.这样Python就不会再使用dict,而且只分配这些属性的空间.

3.png

你还可以用collections.namedtuple,它允许访问参数,但只占用一个tuple的空间.这跟__slots__类似.不过我总觉得继承一个namedtuple类很奇怪.另外,如果你需要自定义初始化,你应该重载__new__而不是__init__.

警告:不要贸然进行这个优化,把它用在所有地方.这种做法不利于代码维护,而且只有当你有数以千计的实例的时候才会有明显效果.

译注:作者在评论中关于”不利于代码维护“的说法:

webreac:我觉得__slots__关键字不只是速度优化(注:这里应该是内存优化),也是类字段名的一个可靠”文档“.这有利于代码维护.为什么你觉得它不好?

Ben Hoyt(作者):有趣的说法——我不确定应不应该把__slots__作为文档.不过的确是不错的注意.我之前这么说的原因是,你需要对字段名”定义“两次(不够DRY).namedtuple也类似.