本日は小ネタ更新です
目次
pyperfを知る
先日PEP 604(PythonでUnion型を|
で表せる)のメーリングリストを覗きました。
その中で、日本人コミッターの稲田さんがパフォーマンスについて述べていました。
https://mail.python.org/archives/list/python-ideas@python.org/message/HHIAHG7MLOL2DP5NXK5OCWC5ENKWOAEW/
$ python3 -m pyperf timeit -s 'from collections.abc import Iterable; x=[]' -- 'isinstance(x, Iterable)'
これがきっかけでpyperfというライブラリを知りました。
pyperf - Toolkit to run Python benchmarks
すごい偶然で、本日3/6付けで最新の2.6.3がリリースされています!🎉
稲田さんの例はpyperf timeit
コマンドを使っています1。
https://github.com/psf/pyperf/tree/2.6.3?tab=readme-ov-file#usage
書式は以下
pyperf timeit stmt
ベンチマークを実行したいコード(文)を書きます。
上の例ではisinstance
関数の実行ですね。
-s
は--setup
オプション。
ベンチマーク対象コードの前に実行したいコードを書きます。
上の例ではIterable
のimportと変数x
の宣言の2つをまとめてですね
他のオプションはpyperf timeit --help
で確認できます。
PEP 604のメーリングリストに見た pyperf は何をやっているのか
ABC has extension module for speedup, but
isinstance([], Iterable)
is 4x slower thanisinstance([], (str, list)
.
PythonのABC(抽象基底クラス)について、速度を上げる拡張モジュールを持っているが、それでもisinstance([], collections.abc.Iterable)
はisinstance([], (str, list))
よりも遅いことを示しています。
M1 Macで再現実験しました。
% sw_vers ProductName: macOS ProductVersion: 12.6.6 BuildVersion: 21G646
- Python 3.12.0
- pyperf 2.6.3
% python3 -m pyperf timeit -s 'from collections.abc import Iterable; x=[]' -- 'isinstance(x, Iterable)' ..................... Mean +- std dev: 123 ns +- 1 ns % python3 -m pyperf timeit -s 'x=[]; T=(str, list)' -- 'isinstance(x, T)' ..................... Mean +- std dev: 30.5 ns +- 1.2 ns
稲田さんが表明している懸念、int | str
のような書き方のパフォーマンス(先日のエントリ参照)を確認してみます。
% python3 -m pyperf timeit -s 'x=[]; T=str | list' -- 'isinstance(x, T)' ..................... Mean +- std dev: 31.3 ns +- 0.6 ns
おー、T=(str, list)
と同様の速さ。
collections.abc.Iterable
とは違いますね。
typing.Union
と比較してみます。
% python3 -m pyperf timeit -s 'from typing import Union; x=[]; T=Union[str, list]' -- 'isinstance(x, T)' ..................... Mean +- std dev: 149 ns +- 2 ns
typing.Union
は遅いのか〜(collections.abc.Iterable
と同程度)。
|
は言語本体でサポートしているから高速ってことなのかな(実力が足りないので今はこの程度の理解。悔しい)
ひとまず宿題が果たせたぞ!🙌
終わりに
pyperf timeit
でPythonコード片のベンチマークを測れます!
Union型まわりのベンチマークを測ってみました。
- 余談ですが、標準ライブラリにtimeitがあります。↩
- https://docs.python.org/ja/3/whatsnew/3.11.html#whatsnew311-faster-cpython 日本語だと「CPython高速化計画」 ↩