18

より複雑な問題に取り組みながら、ローカル変数とメンバー変数のアクセス速度を比較するようになりました。

ここにテストプログラムがあります:

#!/usr/bin/env python

MAX=40000000

class StressTestMember(object):
    def __init__(self):
        self.m = 0

    def do_work(self):
        self.m += 1
        self.m *= 2

class StressTestLocal(object):
    def __init__(self):
        pass

    def do_work(self):
        m = 0
        m += 1
        m *= 2

# LOCAL access test
for i in range(MAX):
    StressTestLocal().do_work()

# MEMBER access test
for i in range(MAX):
    StressTestMember().do_work()

StressTestMember繰り返しごとにインスタンス化するのは悪い考えのように見えるかもしれませんがStressTestLocal、これらが基本的にアクティブレコードであるモデル化されたプログラムでは理にかなっています。

簡単なベンチマークの後、

  • ローカル アクセス テスト: 0m22.836
  • MEMBER アクセステスト: 0m32.648s

ローカル バージョンは、クラスの一部でありながら最大 33% 高速です。なんで?

4

2 に答える 2

29

self.m += 1つまり、呼び出されたローカル変数を検索してからself、呼び出された属性を見つける必要がありますm

もちろん、ローカル変数を検索するだけの場合は、余分な手順がなくても高速になります。

内部で何が起こっているかを調べると便利です。

>>> import dis
>>> dis.dis(StressTestLocal.do_work)
 18           0 LOAD_CONST               1 (0)
              3 STORE_FAST               1 (m)

 19           6 LOAD_FAST                1 (m)
              9 LOAD_CONST               2 (1)
             12 INPLACE_ADD         
             13 STORE_FAST               1 (m)

 20          16 LOAD_FAST                1 (m)
             19 LOAD_CONST               3 (2)
             22 INPLACE_MULTIPLY    
             23 STORE_FAST               1 (m)
             26 LOAD_CONST               0 (None)
             29 RETURN_VALUE        
>>> dis.dis(StressTestMember.do_work)
 10           0 LOAD_FAST                0 (self)
              3 DUP_TOP             
              4 LOAD_ATTR                0 (m)
              7 LOAD_CONST               1 (1)
             10 INPLACE_ADD         
             11 ROT_TWO             
             12 STORE_ATTR               0 (m)

 11          15 LOAD_FAST                0 (self)
             18 DUP_TOP             
             19 LOAD_ATTR                0 (m)
             22 LOAD_CONST               2 (2)
             25 INPLACE_MULTIPLY    
             26 ROT_TWO             
             27 STORE_ATTR               0 (m)
             30 LOAD_CONST               0 (None)
             33 RETURN_VALUE        
于 2012-09-13T01:00:40.073 に答える
7

ローカル名は高速です。Python はローカル名が dict アクセスを必要としないという最適化を行うためです。一方、インスタンス属性__dict__はオブジェクトの にアクセスする必要があります。

これは、ローカル名がグローバル名よりも高速である理由でもあります。

于 2012-09-13T00:57:04.470 に答える