[英]Why does using __slots__ slow down this code?
我读过《 __slots__用法》吗? 在Python中使用__slots__
实际上可以节省时间。 但是,当我尝试找到使用datetime
花费的时间时,结果却相反。
import datetime as t
class A():
def __init__(self,x,y):
self.x = x
self.y = y
t1 = t.datetime.now()
a = A(1,2)
t2 = t.datetime.now()
print(t2-t1)
...给出了输出: 0:00:00.000011
并使用广告位:
import datetime as t
class A():
__slots__ = 'x','y'
def __init__(self,x,y):
self.x = x
self.y = y
t1 = t.datetime.now()
a = A(1,2)
t2 = t.datetime.now()
print(t2-t1)
...给出了输出: 0:00:00.000021
使用插槽实际上花费了更长的时间。 那么为什么我们需要使用__slots__
?
__slots__
可以节省时间(取决于Python版本),但这通常不是您使用的时间。 它真正节省的是内存。 您可以将属性直接存储在支持该对象的C结构中,而不是每个实例都使用相当大的__dict__
,并且类本身也存储查找表从名称到每个属性的结构偏移的映射的单个副本。 即使在具有键共享dict的现代Py3 x64上,键共享__dict__
仍为96字节,其中该类具有单个实例属性,在对象结构本身的56个字节之上。
通过使用__slots__
,可以消除指向__dict__
和__weakref__
属性的指针的16个字节,并完全消除__dict__
。
为了在Py 3.5上进行比较:
>>> class Foo:
... def __init__(self, x): self.x = x
...
>>> sys.getsizeof(Foo(1)) + sys.getsizeof(Foo(1).__dict__)
152
>>> class Foo:
... __slots__ = 'x',
... def __init__(self, x): self.x = x
...
>>> sys.getsizeof(Foo(1)) # With __slots__, doesn't have __dict__ at all
48
这样每个实例可以节省100多个字节。 在Py2(无密钥共享字典)上,节省的费用更大。
因此,并不是说__slots__
通常会更快(通常非常相似),但是如果您要创建数百万个实例,则为每个实例节省100+ B可能会帮助您将代码保留在缓存,RAM等中,而不是在运行内存不足并分页出一半数据以进行交换。
如其他答案所述,您实际上从未访问过属性,因此根本就没有基准测试插槽访问权限,这就是为什么您看不到任何区别的原因。 使用ipython3
%%timeit
魔术,我发现重复加载给定实例的x
属性时,将其ipython3
时大约快15%(带__slots__
加载时间为33.5 ns,不带__slots__
为39.2 ns),但这仅在微基准测试中可见; 在实际代码中(在实际工作中所做的不仅仅是属性查找而已)还很少。 重要的是,将内存使用量减少2-3倍是更大的收益。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.