看了一下 tech.oyster.com/save-ram-wi… 这篇文章,该作者发现通过使用__slots__ 可以让内存从25.5GB降到16.2GB,效果显著,节约了大量资源了。于是,我也通过例子实现了一遍,加深一下理解。
import sys
import resource # 该库只能用于unix中
class NotUseSlots(object):
def __init__(self):
# 初始化属性
self.test_string = 'This Type is string'
self.test_int = 300
self.test_bool = False
class UseSlots(object):
__slots__ = ['test_string', 'test_int', 'test_bool']
def __init__(self):
self.test_string = 'This Type is string'
self.test_int = 300
self.test_bool = False
def test(cls):
mem_init = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
lists = []
for i in range(50000):
lists.append(cls())
mem_final = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
del lists
print('Class: {0}:\n'.format(getattr(cls, '__name__')))
print('Initial RAM usage:{:14,}'.format(mem_init))
print('Final RAM usage: {:14,}'.format(mem_final))
print('-'*20)
if __name__ == '__main__':
test(globals()[sys.argv[1]])
我分别测试了这两个测试类NotUseSlots和UseSlots:
root@python:/data# python test_slots.py NotUseSlots
Class: NotUseSlots:
Initial RAM usage: 6,624
Final RAM usage: 15,468
--------------------
root@python:/data# python test_slots.py UseSlots
Class: UseSlots:
Initial RAM usage: 6,624
Final RAM usage: 10,092
--------------------
root@python:/data#
通过计算(15468-6624)/(10092-6624)发现未使用__slots__的内存消耗为使用__slots__的内存消耗使用2.25倍左右。(百万级是3.5倍左右) 所以可以根据实际需求相应的优化一下代码,节约服务器内存资源。
__slots__实现原理
__slots__中变量是类属性,类型为数据描述符(这篇文章写得不错 blog.csdn.net/lis_12/arti… 可以看看)。
虽然其变量是类属性但不同实例互不影响。因为描述符方法的一个参数为实例,建立一个实例和值的映射很轻松。
如果类定义了__slots__ ,该类的实例不会有__dict__属性。实例中__dict__属性是非常消耗内存的,当创建上百万级以上实例的时候,所有实例的__dict__会消耗大量内存。没有了__dict__的实例是无法动态添加属性的,而只能分配固定内存来缓存已知的__slots__里的属性。所以这也是使用了__slots__的类可以节约很多内存开销的原因吧。
因此对于不需要动态添加属性的类且实例在万级以上时,可以考虑使用__slots__来进行优化,万级以下效果不明显。