fast-woothee-pythonを書いていました
woothee-rustがwootheeファミリー(organization)に追加されました https://t.co/qBYm2NAv4o
— Hideo Hattori (@hhatto) 2017年8月21日
少し前の話ですが、 8月頃にwoothee-goにプルリクを送った 流れから中の人に提案していただいて、 woothee-rust をwootheeファミリに追加していただけました。
fast_woothee
その流れからwootheeまわりを調べていると、 速度を求めてか woothee-rustのRubyバインディングfast_woothee というものがありまして、 ほぉという感じで眺めていました。 少し時が経って、じゃぁ実際どれくらい速いのか確認したくなったので、 確認してみるとRubyネイティブ実装の woothee-ruby より遅かったのです。 どうしたものかと思って、 woothee-rustのdatasetまわりのコードをlazy_staticでラップして高速化 しました。 結果2倍ほど高速になりました 。
[before] $ ruby bench.rb user system total real woothee 2.270000 0.020000 2.290000 ( 2.309573) fast-woothee 2.710000 0.020000 2.730000 ( 2.758268) [after] $ ruby bench.rb user system total real woothee 2.240000 0.020000 2.260000 ( 2.261497) fast-woothee 1.100000 0.010000 1.110000 ( 1.134596)
fast-woothee-python
さてここからが本題なのですが、fast_wootheeの流れを受けて Pythonでも同じようなことをしたくなったのでさっくり実装してみました。
モチベーションとしては、以下のようなものでした。
- Pythonでも同等の高速化が期待できる
- 一定API自体は固まっておりほぼ変わらないので、 一度拡張を書いてしまえばwoothee-rustをメンテナンスすることで変更に対応でき、 メンテナンスコストを低減できる。
- RustなPython拡張の事例作り(今後プロダクションで使っていきたい)
結果はこちらも 約3倍程度の高速化が実現 できました。
## benchmarker: release 4.0.1 (for python) ## python version: 2.7.13 ## python compiler: GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1) ## python platform: Darwin-15.6.0-x86_64-i386-64bit ## python executable: ./.virtualenvs/py2713/bin/python ## cpu model: Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz ## parameters: loop=100000, cycle=1, extra=0 ## real (total = user + sys) uap 0.0813 0.0800 0.0800 0.0000 uap(non-cache) 64.3114 63.5200 63.2800 0.2400 woothee 3.2219 3.1200 3.1000 0.0200 fast-woothee 1.0989 1.1000 1.0900 0.0100 ## Ranking real uap 0.0813 (100.0) ******************** fast-woothee 1.0989 ( 7.4) * woothee 3.2219 ( 2.5) * uap(non-cache) 64.3114 ( 0.1) ## Matrix real [01] [02] [03] [04] [01] uap 0.0813 100.0 1352.1 3964.4 79132.1 [02] fast-woothee 1.0989 7.4 100.0 293.2 5852.5 [03] woothee 3.2219 2.5 34.1 100.0 1996.1 [04] uap(non-cache) 64.3114 0.1 1.7 5.0 100.0
uap-python (uap)はキャッシュを内部で持っていて、 一度パースした結果をすぐに返せるので非常に高速になってます。 キャッシュを使わない場合も参考に載せてます。uap(non-cache)
implementation
fast-woothee-pythonはRustコードを書くことでPython拡張が書ける PyO3/pyo3 を使っています。 同じ用途として dgrunwald/rust-cpython が存在するのですが、 私が試した時はPython2向けのビルドがエラーになってしまったのと、 Python3でベンチマークをとってみてもオーバーヘッドがどちらも同じくらいだったので、 pyo3を使った経緯があります。 pyo3の方が活発に開発が行われていますが、rust-cpythonも開発が止まっているわけではないので、 今は状況が変わっているかもしれません。
parse メソッドと is_crawler メソッドの2つしかなく最小限の構成になっているので、 RustなPython拡張の雛形として参考にしていただければと。