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


Posted in Python onApril 02, 2015

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

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

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

我们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 相关文章推荐
Python help()函数用法详解
Mar 11 Python
python常用知识梳理(必看篇)
Mar 23 Python
Python实现的质因式分解算法示例
May 03 Python
numpy 进行数组拼接,分别在行和列上合并的实例
May 08 Python
详解关于Django中ORM数据库迁移的配置
Oct 08 Python
浅谈python中拼接路径os.path.join斜杠的问题
Oct 23 Python
在PyCharm中批量查找及替换的方法
Jan 20 Python
Python面向对象实现一个对象调用另一个对象操作示例
Apr 08 Python
详解PyCharm安装MicroPython插件的教程
Jun 24 Python
python基于opencv检测程序运行效率
Dec 28 Python
Python如何通过Flask-Mail发送电子邮件
Jan 29 Python
python re.match()用法相关示例
Jan 27 Python
用Python的线程来解决生产者消费问题的示例
Apr 02 #Python
用实例分析Python中method的参数传递过程
Apr 02 #Python
使用优化器来提升Python程序的执行效率的教程
Apr 02 #Python
使用Python脚本对Linux服务器进行监控的教程
Apr 02 #Python
在Python编程过程中用单元测试法调试代码的介绍
Apr 02 #Python
用Python的Django框架完成视频处理任务的教程
Apr 02 #Python
用map函数来完成Python并行任务的简单示例
Apr 02 #Python
You might like
用PHP实现小型站点广告管理(修正版)
2006/10/09 PHP
使用PHP获取网络文件的实现代码
2010/01/01 PHP
vs中通过剪切板循环来循环粘贴不同内容
2011/04/30 PHP
PHP文件缓存smarty模板应用实例分析
2016/02/26 PHP
php根据数据id自动生成编号的实现方法
2016/10/16 PHP
PHP中危险的file_put_contents函数详解
2017/11/04 PHP
IE6下js通过css隐藏select的一个bug
2010/08/16 Javascript
jquery及原生js获取select下拉框选中的值示例
2013/10/25 Javascript
jQuery实现html表格动态添加新行的方法
2015/05/28 Javascript
论Bootstrap3和Foundation5网格系统的异同
2016/05/16 Javascript
jquery if条件语句的写法
2016/05/19 Javascript
详解JavaScript对象类型
2016/06/16 Javascript
jQuery中的一些小技巧
2017/01/18 Javascript
php输出全部gb2312编码内的汉字方法
2017/03/04 Javascript
React全家桶环境搭建过程详解
2018/05/18 Javascript
利用jquery和BootStrap实现动态滚动条效果
2018/12/03 jQuery
JS自定义对象创建与简单使用方法示例
2020/01/15 Javascript
JavaScript Event Loop相关原理解析
2020/06/10 Javascript
Linux下安装python3.6和第三方库的教程详解
2018/11/09 Python
Linux上使用Python统计每天的键盘输入次数
2019/04/17 Python
Otel.com:折扣酒店预订
2017/08/24 全球购物
严选全球尖货,立足香港:Bonpont宝盆
2018/07/24 全球购物
中学生团员自我评价分享
2013/12/07 职场文书
奥利奥广告词
2014/03/20 职场文书
小学生倡议书范文
2014/05/13 职场文书
安全生产宣传标语
2014/06/06 职场文书
2014年新农村建设工作总结
2014/12/01 职场文书
小学感恩主题班会
2015/08/12 职场文书
《夹竹桃》教学反思
2016/02/23 职场文书
对PyTorch中inplace字段的全面理解
2021/05/22 Python
Python函数中的不定长参数相关知识总结
2021/06/24 Python
Window server中安装Redis的超详细教程
2021/11/17 Redis
SQLServer中exists和except用法介绍
2021/12/04 SQL Server
Python中的tkinter库简单案例详解
2022/01/22 Python
JavaScript的Set数据结构详解
2022/02/18 Javascript
java实现自定义时钟并实现走时功能
2022/06/21 Java/Android