用Python中的__slots__缓存资源以节省内存开销的方法

yipeiwu_com6年前Python基础

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

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

201542170958351.jpg (862×280)

我们alloc了大约一百万个类似如下class的实例:
 
class Image(object):
    def __init__(self, id, caption, url):
        self.id = id
        self.caption = caption
        self.url = url
        self._setup()
 
    # ... other methods ...

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

但是,对一些在”编译”前就知道该有几个固定属性的小class来说,这个dict就有点浪费内存了。而当你把这个小浪费乘上一百万,那可就大不同了。在Python中,你可以在class中设置__slots__,它是一个包含这些固定的属性名的list。这样Python就不会再使用dict,而且只分配这些属性的空间。
 
class Image(object):
    __slots__ = ['id', 'caption', 'url']
 
    def __init__(self, id, caption, url):
        self.id = id
        self.caption = caption
        self.url = url
        self._setup()
 
    # ... other methods ...

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

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

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

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

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

相关文章

Python lxml解析HTML并用xpath获取元素的方法

代码 使用方法见注释 #-*- coding: UTF-8 -*- from lxml import etree source = u''' <div><p c...

Python实现Pig Latin小游戏实例代码

前言: 本文研究的主要是Python实现pig Latin小游戏的简单代码,具体介绍如下。 Pig Latin是一个语言游戏。 步骤: 1.让用户输入一个英文单词 2.确保用户输入...

python 将字符串完成特定的向右移动方法

# 将字符串中的元素完成特定的向右移动,参数:字符串、移动长度 如:abcdef,移动2,结果:efabcd #原始方法,基本思想:末尾元素移动到开头,其他的元素依次向后移动.代码如下:...

500行代码使用python写个微信小游戏飞机大战游戏

500行代码使用python写个微信小游戏飞机大战游戏

这几天在重温微信小游戏的飞机大战,玩着玩着就在思考人生了,这飞机大战怎么就可以做的那么好,操作简单,简单上手。 帮助蹲厕族、YP族、饭圈女孩在无聊之余可以有一样东西让他们振作起来!让他们...

python 转换 Javascript %u 字符串为python unicode的代码

web采集的数据为 %u6B63%u5F0F%u4EBA%u5458,需要读取并转换为python对象,想了下不调用Javascript去eval,只能自己翻译了。 核心代码: i...