2016年1月10日

ベンチマーク11 lazy import

lazy import の3つのやり方について、繰り返し import 箇所を呼んだ場合の速度を計測します。


まず、ループの中で math.pi を一度だけ呼び出す処理のベンチマークを計測します。
ベンチマークのソースコードです。

from benchmarker import Benchmarker

# グローバル変数と専用クラスは先に定義
g_math = __import__('math')
c_math = LazyImport('math')

with Benchmarker(1000000, cycle=3, extra=1) as bench:

    @bench("local")
    def _(bm):
        for _ in bm:
            import math
            math.pi

    @bench("global")
    def _(bm):
        for _ in bm:
            global g_math
            if g_math is None:
                g_math = __import__('math')
            g_math.pi

    @bench("class")
    def _(bm):
        for _ in bm:
            c_math.pi

計測結果です。
## benchmarker:         release 4.0.1 (for python)
## python version:      3.4.0
## python compiler:     MSC v.1600 32 bit (Intel)
## python platform:     Windows-8-6.2.9200
...

## Ranking     real
global       0.5394  (100.0) ********************
local        5.1763  ( 10.4) **
class        5.2870  ( 10.2) **
計測結果からは、グローバル変数式が圧倒的に高速となりました。
この計測では、ローカルimport と LazyImportクラスはほぼ等速です。


続けて、ループの中で math.pi を2回呼び出す処理のベンチマークを計測します。
ベンチマークのソースコードです。

from benchmarker import Benchmarker

# グローバル変数と専用クラスは先に定義
g_math = __import__('math')
c_math = LazyImport('math')

with Benchmarker(1000000, cycle=3, extra=1) as bench:

    @bench("local")
    def _(bm):
        for _ in bm:
            import math
            math.pi
            math.pi

    @bench("global")
    def _(bm):
        for _ in bm:
            global g_math
            if g_math is None:
                g_math = __import__('math')
            g_math.pi
            g_math.pi

    @bench("class")
    def _(bm):
        for _ in bm:
            c_math.pi
            c_math.pi

計測結果です。
## benchmarker:         release 4.0.1 (for python)
## python version:      3.4.0
## python compiler:     MSC v.1600 32 bit (Intel)
## python platform:     Windows-8-6.2.9200
...

## Ranking     real
global       0.7084  (100.0) ********************
local        5.4640  ( 13.0) ***
class       10.2182  (  6.9) *
グローバル変数式が相変わらず速いです。
そして、LazyImportクラスは如実に遅くなりました。これは、LazyImportクラスは参照される度に getattr() を呼ぶことが原因です。


結論として、以下の2つが言えます。

  • import は2回目以降でもそれなりに重い処理である。よって、import 箇所に繰り返し通る可能性があるなら、グローバル変数式を使うべき。
  • LazyImportクラスは動作が遅い。元々高速化のための lazy import であるのに、これではあまり使い道がない。

0 件のコメント:

コメントを投稿