繁体   English   中英

为什么使用__slots__会减慢此代码的速度?

[英]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倍是更大的收益。

  1. 您引用的文章说使用插槽提供了更快的属性访问 -您测试了对象创建的时间,并且从未访问过对象的属性。
  2. 测试单个操作在统计上没有意义-测量例如100000次操作的时间。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM