栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

为什么检查isinstance(某事,映射)这么慢?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

为什么检查isinstance(某事,映射)这么慢?

性能实际上只是与ABCmeta的

__instancecheck__
支票集合联系在一起,这称为
isinstance

最重要的是,这里看到的性能不佳不是由于缺少一些优化,而是

isinstance
Jim提到的抽象基类是Python级别的操作的结果。正和负的结果都会被缓存,但是即使有缓存的结果,您也要在每个循环中花几微秒的时间来遍历
__instancecheck__
ABCmeta类方法中的条件。


一个例子

考虑一些不同的空结构。

>>> d = dict; l = list(); s = pd.Series()>>> %timeit isinstance(d, collections.abc.Mapping)100000 loops, best of 3: 1.99 µs per loop>>> %timeit isinstance(l, collections.abc.Mapping)100000 loops, best of 3: 3.16 µs per loop # caching happening>>> %timeit isinstance(s, collections.abc.Mapping)100000 loops, best of 3: 3.26 µs per loop # caching happening

我们可以看到性能差异-是什么原因造成的?

为了一个命令

>>> %lprun -f abc.ABCmeta.__instancecheck__ isinstance(dict(), collections.abc.Mapping)Timer unit: 6.84247e-07 sTotal time: 1.71062e-05 sLine #      Hits         Time  Per Hit   % Time  Line Contents==============================================================   178   def __instancecheck__(cls, instance):   179       """Override for isinstance(instance, cls)."""   180       # Inline the cache checking   181         1 7      7.0     28.0          subclass = instance.__class__   182         116     16.0     64.0          if subclass in cls._abc_cache:   183         1 2      2.0      8.0   return True   184       subtype = type(instance)   185       if subtype is subclass:   186if (cls._abc_negative_cache_version ==   187    ABCmeta._abc_invalidation_counter and   188    subclass in cls._abc_negative_cache):   189    return False   190# Fall back to the subclass check.   191return cls.__subclasscheck__(subclass)   192       return any(cls.__subclasscheck__(c) for c in {subclass, subtype})

清单

>>> %lprun -f abc.ABCmeta.__instancecheck__ isinstance(list(), collections.abc.Mapping)Timer unit: 6.84247e-07 sTotal time: 3.07911e-05 sLine #      Hits         Time  Per Hit   % Time  Line Contents==============================================================   178   def __instancecheck__(cls, instance):   179       """Override for isinstance(instance, cls)."""   180       # Inline the cache checking   181         1 7      7.0     15.6          subclass = instance.__class__   182         117     17.0     37.8          if subclass in cls._abc_cache:   183return True   184         1 2      2.0      4.4          subtype = type(instance)   185         1 2      2.0      4.4          if subtype is subclass:   186         1 3      3.0      6.7   if (cls._abc_negative_cache_version ==   187         1 2      2.0      4.4       ABCmeta._abc_invalidation_counter and   188         110     10.0     22.2       subclass in cls._abc_negative_cache):   189         1 2      2.0      4.4       return False   190# Fall back to the subclass check.   191return cls.__subclasscheck__(subclass)   192       return any(cls.__subclasscheck__(c) for c in {subclass, subtype})

我们可以看到,对于dict,映射抽象类的

_abc_cache

>>> list(collections.abc.Mapping._abc_cache)[dict]

包括我们的字典,因此检查会尽早短路。对于列表,显然不会命中正缓存,但是“映射”

_abc_negative_cache
包含列表类型

>>> list(collections.abc.Mapping._abc_negative_cache)[type, list, generator, pandas.core.series.Series, itertools.chain, int, map]

以及现在的pd.Series类型,这是因为使用

isinstance
多次调用了
%timeit
。在我们没有命中负缓存的情况下(例如Series的第一次迭代),Python会使用带有

cls.__subclasscheck__(subclass)

其可以是
慢,诉诸子类钩和递归子类检查这里看到,那么高速缓存用于随后的加速比的结果。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/668029.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号