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

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

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

我们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也类似。

(0)

相关推荐

  • Python中的__slots__示例详解

    前言 相信Python老鸟都应该看过那篇非常有吸引力的Saving 9 GB of RAM with Python's slots文章,作者使用了__slots__让内存占用从25.5GB降到了16.2GB.在当时来说,这相当于用一个非常简单的方式就降低了30%的内存使用,着实惊人.作者并没有提到他的业务特点和代码,那我们就基于<fluent python>中的例子来验证下是不是有这么厉害: from __future__ import print_function import resour

  • python中的__slots__使用示例

    正常情况下,当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性.先定义class: 复制代码 代码如下: >>> class Staff(object): ...     pass ... 然后,尝试给实例绑定一个属性: 复制代码 代码如下: >>> s = Staff() >>> s.name = 'jack' >>> print s.name jack >&g

  • 在Python中使用__slots__方法的详细教程

    正常情况下,当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性.先定义class: >>> class Student(object): ... pass ... 然后,尝试给实例绑定一个属性: >>> s = Student() >>> s.name = 'Michael' # 动态给实例绑定一个属性 >>> print s.name Michael 还可以尝试给实例

  • Python中的__SLOTS__属性使用示例

    看python社区大妈组织的内容里边有一篇讲python内存优化的,用到了__slots__.然后查了一下,总结一下.感觉非常有用 python类在进行实例化的时候,会有一个__dict__属性,里边有可用的实例属性名和值.声明__slots__后,实例就只会含有__slots__里有的属性名. # coding: utf-8 class A(object): x = 1 def __init__(self): self.y = 2 a = A() print a.__dict__ print(

  • python中__slots__用法实例

    本文实例讲述了python中__slots__的用法.分享给大家供大家参考.具体分析如下: 定义__slots__ 后,可以再实例上分配的属性名称将被限制为指定的名称.否则将引发AttributeError,这种限制可以阻止其他人向现有的实例添加新的属性.   使用__slots__的类的实例不在使用字典来存储数据.相反,会使用基于数组的更加紧凑的数据结构. 在会创建大量对象的程序中,使用__slots__可以显著减少内存占用和使用时间 class Account(object): __slot

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

    我们曾经提到,Oyster.com的Python web服务器怎样利用一个巨大的Python dicts(hash table),缓存大量的静态资源.我们最近在Image类中,用仅仅一行__slots__代码,让每个6G内存占用的服务进程(共4个),省出超过2G来. 这是其中一个服务器在部署代码前后的截图: 我们alloc了大约一百万个类似如下class的实例:   class Image(object):     def __init__(self, id, caption, url):   

  • Python中字典的缓存池

    目录 PyDictObject缓存池 PyDictKeysObject缓存池 小结 前言: 我们知道字典里面有一个ma_keys和ma_values,其中ma_keys是一个指向PyDictKeysObject的指针,ma_values是一个指向PyObject *数组的二级指针.当哈希表为分离表时,键由ma_keys维护,值由ma_values维护:当哈希表为结合表时,键和值均由ma_keys维护. 那么当我们在销毁一个PyDictObject时,也肯定是要先释放ma_keys和ma_valu

  • python中print的不换行即时输出的快速解决方法

    关于Python2.x和3.x带来的print不换行的问题:昨天有发过推文,利用end = 定义,解决了横向的小问题,但是由于屏幕显示的问题,若字符串长度过大,则会引起不便.两个或多个print做分割的情况下,如何保持依然横向输出,一般的是在print尾部加上逗号(,)但是在3.x下,则不行,需要使用end = "(something)",some signs like , . ; 'also you can put a word or str in"". Exam

  • Python中实现两个字典(dict)合并的方法

    本文实例讲述了Python中实现两个字典(dict)合并的方法,分享给大家供大家参考.具体方法如下: 现有两个字典dict如下: dict1={1:[1,11,111],2:[2,22,222]} dict2={3:[3,33,333],4:[4,44,444]} 合并两个字典得到类似: {1:[1,11,111],2:[2,22,222],3:[3,33,333],4:[4,44,444]} 方法1: dictMerged1=dict(dict1.items()+dict2.items())

  • Python中实现变量赋值传递时的引用和拷贝方法

    iamlaosong文 曾经看到这样一个问题,一个字典中的元素是列表,将这个列表元素赋值给一个变量,然后修改这个列表中元素的值,结果发现,字典中那个列表也同样修改了. 那个问题如下: dict = {'a':[1,2,3,4,5],'b':2} x = dict['a'] for i in range(5): x[i] = 0 print(dict['a']) 程序运行结果如下: [0, 0, 0, 0, 0] 这儿涉及到Python赋值到底是引用还是拷贝一份的问题,即赋值时是传值还是传址.上面

  • Python中py文件引用另一个py文件变量的方法

    最近自己初学Python,在编程是遇到一个问题就是,怎样在一个py文件中使用另一个py文件中变量,问题如下: demo1代码 import requests r = requests.get("http://www.baidu.com") r.encoding = r.apparent_encoding demo = r.text demo beauful1代码: from bs4 import BeautifulSoup soup = BeautifulSoup(demo,"

  • Python中多个数组行合并及列合并的方法总结

    采用numpy快速将两个矩阵或数组合并成一个数组: import numpy as np 数组 a = [[1,2,3],[4,5,6]] b = [[1,1,1],[2,2,2]] 1.数组纵向合并 1) c = np.vstack((a,b)) c = array([[1, 2, 3], [4, 5, 6], [1, 1, 1], [2, 2, 2]] 2) c = np.r_[a,b] c = array([[1, 2, 3], [4, 5, 6], [1, 1, 1], [2, 2, 2

  • 在Python 中同一个类两个函数间变量的调用方法

    如下所示: class A(): def test_a(self): self.m ="hello" def test_b(self): self.test_a() n=self.m + "world" print(n) if __name__ == '__main__': A().test_b() 运行结果: 以上这篇在Python 中同一个类两个函数间变量的调用方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • 在python中对变量判断是否为None的三种方法总结

    三种主要的写法有: 第一种:if X is None; 第二种:if not X: 当X为None,  False, 空字符串"", 0, 空列表[], 空字典{}, 空元组()这些时,not X为真,即无法分辨出他们之间的不同. 第三种:if not X is None; 在Python中,None.空列表[].空字典{}.空元组().0等一系列代表空和无的对象会被转换成False.除此之外的其它对象都会被转化成True. 在命令if not 1中,1便会转换为bool类型的True

  • Python中对数组集进行按行打乱shuffle的方法

    如下所示: import numpy as np y1=np.random.randint(2,10,(5,3)) print ("排序列表:", y1) np.random.shuffle(y1) print ("随机排序列表:", y1) 以上这篇Python中对数组集进行按行打乱shuffle的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

随机推荐