「python Advent Calendar 2017 10日目」 の記事です。
TwitterのTLをぼーっと眺めていたら気になるサイトを見つけました。
Check This Out – Optimized Python
なんと、このdockerイメージを使うと、公式のPythonのイメージと比較して、19%の高速化と75%の軽量化がされているようです。 これは試さずにはいられません。
ビルドされたイメージは Docker Hub に上がっており、イメージをpullするだけで最適化されたPythonが使えます。
Pythonのバージョンは3.5.4および3.6.3が用意されているようです。 1
イメージのサイズはGitLabやGitHubのREADMEを見る限りだと下記のようになっているようです。
REPOSITORY  | 
TAG  | 
SIZE  | 
|---|---|---|
python  | 
3.6.3  | 
690MB  | 
python  | 
3.6-slim  | 
201MB  | 
python  | 
3.6.3-alpine  | 
89MB  | 
registry.gitlab.com/revsys/docker-builds/python  | 
3.6.3-wee  | 
153MB  | 
さすがにalpineをベースにしたイメージよりは大きくなっていますが、非常にコンパクトにまとまっています。 Debian 8ベースなので、many linux wheelのパッケージが使えるのが大きな利点です。 ちなみに筆者はalpineベースでイメージを作ったことがありますが、pipインストール時にビルドが必要なパッケージを入れようとして何度も泣いたことがあります(´°̥̥̥̥̥̥̥̥ω°̥̥̥̥̥̥̥̥`)
早速ベンチマークをとってみましょう。筆者のHW環境は下記のとおりです。 2010年くらいのモデルですが未だ現役で使ってます...早くRyzen MobileのPCでないかなぁ...
Architecture:  | 
x86_64  | 
CPU op-mode(s):  | 
32-bit, 64-bit  | 
Byte Order:  | 
Little Endian  | 
CPU(s):  | 
4  | 
On-line CPU(s) list:  | 
0-3  | 
Thread(s) per core:  | 
2  | 
Core(s) per socket:  | 
2  | 
Socket(s):  | 
1  | 
NUMA node(s):  | 
1  | 
Vendor ID:  | 
GenuineIntel  | 
CPU family:  | 
6  | 
Model:  | 
37  | 
Model name:  | 
Intel(R) Core(TM) i5 CPU M 520 @ 2.40GHz  | 
Stepping:  | 
5  | 
CPU MHz:  | 
1333.000  | 
CPU max MHz:  | 
2400.0000  | 
CPU min MHz:  | 
1199.0000  | 
BogoMIPS:  | 
4788.43  | 
Virtualization:  | 
VT-x  | 
L1d cache:  | 
32K  | 
L1i cache:  | 
32K  | 
L2 cache:  | 
256K  | 
L3 cache:  | 
3072K  | 
NUMA node0 CPU(s):  | 
0-3  | 
下記の3つのパターンでベンチマークしています、ベンチマークには pyperformance というライブラリを使いました。
公式のPythonイメージ: python:3.6.3
Optimized Pythonイメージ: python:3.6.3-wee-optimized-lto
OSのPython3.6.3: Ubuntu 17.10
結果は下記のとおりです。
Benchmark  | 
docker  | 
docker optimized  | 
system  | 
|---|---|---|---|
2to3  | 
1.09 sec  | 
954 ms: 1.15x faster (-13%)  | 
1.21 sec: 1.10x slower (+10%)  | 
chameleon  | 
39.7 ms  | 
30.4 ms: 1.31x faster (-23%)  | 
34.7 ms: 1.14x faster (-12%)  | 
chaos  | 
414 ms  | 
355 ms: 1.17x faster (-14%)  | 
350 ms: 1.18x faster (-15%)  | 
crypto_pyaes  | 
310 ms  | 
281 ms: 1.10x faster (-9%)  | 
283 ms: 1.09x faster (-9%)  | 
deltablue  | 
25.7 ms  | 
21.4 ms: 1.20x faster (-17%)  | 
21.7 ms: 1.18x faster (-15%)  | 
django_template  | 
617 ms  | 
490 ms: 1.26x faster (-21%)  | 
531 ms: 1.16x faster (-14%)  | 
fannkuch  | 
1.38 sec  | 
1.23 sec: 1.12x faster (-11%)  | 
1.25 sec: 1.10x faster (-9%)  | 
float  | 
328 ms  | 
309 ms: 1.06x faster (-6%)  | 
305 ms: 1.08x faster (-7%)  | 
genshi_text  | 
121 ms  | 
103 ms: 1.17x faster (-15%)  | 
109 ms: 1.11x faster (-10%)  | 
genshi_xml  | 
268 ms  | 
223 ms: 1.21x faster (-17%)  | 
240 ms: 1.12x faster (-11%)  | 
go  | 
846 ms  | 
717 ms: 1.18x faster (-15%)  | 
741 ms: 1.14x faster (-12%)  | 
hexiom  | 
32.9 ms  | 
27.8 ms: 1.18x faster (-16%)  | 
29.9 ms: 1.10x faster (-9%)  | 
html5lib  | 
343 ms  | 
290 ms: 1.18x faster (-16%)  | 
306 ms: 1.12x faster (-11%)  | 
json_dumps  | 
40.3 ms  | 
34.5 ms: 1.17x faster (-14%)  | 
37.2 ms: 1.08x faster (-8%)  | 
json_loads  | 
79.3 us  | 
66.0 us: 1.20x faster (-17%)  | 
72.4 us: 1.10x faster (-9%)  | 
logging_format  | 
47.8 us  | 
38.9 us: 1.23x faster (-19%)  | 
41.0 us: 1.17x faster (-14%)  | 
logging_silent  | 
1.02 us  | 
936 ns: 1.09x faster (-9%)  | 
909 ns: 1.13x faster (-11%)  | 
logging_simple  | 
39.4 us  | 
32.1 us: 1.22x faster (-18%)  | 
34.4 us: 1.14x faster (-13%)  | 
mako  | 
63.0 ms  | 
51.6 ms: 1.22x faster (-18%)  | 
54.5 ms: 1.16x faster (-14%)  | 
meteor_contest  | 
278 ms  | 
237 ms: 1.17x faster (-15%)  | 
248 ms: 1.12x faster (-11%)  | 
nbody  | 
304 ms  | 
329 ms: 1.08x slower (+8%)  | 
281 ms: 1.08x faster (-7%)  | 
nqueens  | 
355 ms  | 
318 ms: 1.11x faster (-10%)  | 
311 ms: 1.14x faster (-12%)  | 
pathlib  | 
84.3 ms  | 
64.6 ms: 1.30x faster (-23%)  | 
62.2 ms: 1.35x faster (-26%)  | 
pickle  | 
32.0 us  | 
26.1 us: 1.23x faster (-18%)  | 
26.8 us: 1.20x faster (-16%)  | 
pickle_dict  | 
78.2 us  | 
66.5 us: 1.18x faster (-15%)  | 
58.0 us: 1.35x faster (-26%)  | 
pickle_list  | 
10.7 us  | 
8.90 us: 1.21x faster (-17%)  | 
8.75 us: 1.23x faster (-19%)  | 
pickle_pure_python  | 
1.81 ms  | 
1.60 ms: 1.14x faster (-12%)  | 
1.63 ms: 1.11x faster (-10%)  | 
pidigits  | 
378 ms  | 
not significant  | 
368 ms: 1.03x faster (-3%)  | 
python_startup  | 
30.4 ms  | 
27.6 ms: 1.10x faster (-9%)  | 
27.7 ms: 1.10x faster (-9%)  | 
python_startup_no_site  | 
20.8 ms  | 
19.3 ms: 1.08x faster (-7%)  | 
18.8 ms: 1.11x faster (-10%)  | 
raytrace  | 
1.94 sec  | 
1.66 sec: 1.17x faster (-15%)  | 
1.63 sec: 1.19x faster (-16%)  | 
regex_compile  | 
630 ms  | 
529 ms: 1.19x faster (-16%)  | 
568 ms: 1.11x faster (-10%)  | 
regex_dna  | 
365 ms  | 
340 ms: 1.07x faster (-7%)  | 
355 ms: 1.03x faster (-3%)  | 
regex_effbot  | 
6.34 ms  | 
6.18 ms: 1.03x faster (-3%)  | 
6.10 ms: 1.04x faster (-4%)  | 
regex_v8  | 
60.5 ms  | 
54.2 ms: 1.12x faster (-10%)  | 
55.2 ms: 1.10x faster (-9%)  | 
richards  | 
264 ms  | 
231 ms: 1.14x faster (-12%)  | 
235 ms: 1.12x faster (-11%)  | 
scimark_fft  | 
908 ms  | 
939 ms: 1.03x slower (+3%)  | 
805 ms: 1.13x faster (-11%)  | 
scimark_lu  | 
691 ms  | 
594 ms: 1.16x faster (-14%)  | 
not significant  | 
scimark_monte_carlo  | 
387 ms  | 
328 ms: 1.18x faster (-15%)  | 
325 ms: 1.19x faster (-16%)  | 
scimark_sor  | 
717 ms  | 
604 ms: 1.19x faster (-16%)  | 
669 ms: 1.07x faster (-7%)  | 
scimark_sparse_mat_mult  | 
11.7 ms  | 
not significant  | 
9.74 ms: 1.20x faster (-17%)  | 
spectral_norm  | 
339 ms  | 
329 ms: 1.03x faster (-3%)  | 
328 ms: 1.03x faster (-3%)  | 
sqlalchemy_declarative  | 
440 ms  | 
406 ms: 1.08x faster (-8%)  | 
394 ms: 1.12x faster (-10%)  | 
sqlalchemy_imperative  | 
90.9 ms  | 
80.4 ms: 1.13x faster (-12%)  | 
82.5 ms: 1.10x faster (-9%)  | 
sqlite_synth  | 
12.6 us  | 
11.1 us: 1.14x faster (-12%)  | 
10.4 us: 1.21x faster (-18%)  | 
sympy_expand  | 
1.55 sec  | 
1.27 sec: 1.22x faster (-18%)  | 
1.34 sec: 1.16x faster (-13%)  | 
sympy_integrate  | 
66.7 ms  | 
55.0 ms: 1.21x faster (-17%)  | 
58.7 ms: 1.14x faster (-12%)  | 
sympy_sum  | 
313 ms  | 
259 ms: 1.21x faster (-17%)  | 
275 ms: 1.14x faster (-12%)  | 
sympy_str  | 
689 ms  | 
569 ms: 1.21x faster (-17%)  | 
598 ms: 1.15x faster (-13%)  | 
telco  | 
29.0 ms  | 
21.1 ms: 1.37x faster (-27%)  | 
25.6 ms: 1.13x faster (-12%)  | 
tornado_http  | 
612 ms  | 
527 ms: 1.16x faster (-14%)  | 
549 ms: 1.12x faster (-10%)  | 
unpack_sequence  | 
143 ns  | 
139 ns: 1.03x faster (-3%)  | 
139 ns: 1.03x faster (-3%)  | 
unpickle  | 
43.1 us  | 
38.0 us: 1.13x faster (-12%)  | 
37.1 us: 1.16x faster (-14%)  | 
unpickle_list  | 
8.95 us  | 
7.90 us: 1.13x faster (-12%)  | 
not significant  | 
unpickle_pure_python  | 
1.20 ms  | 
1.07 ms: 1.11x faster (-10%)  | 
1.14 ms: 1.05x faster (-5%)  | 
xml_etree_parse  | 
379 ms  | 
343 ms: 1.10x faster (-9%)  | 
390 ms: 1.03x slower (+3%)  | 
xml_etree_iterparse  | 
329 ms  | 
292 ms: 1.13x faster (-11%)  | 
301 ms: 1.09x faster (-8%)  | 
xml_etree_generate  | 
387 ms  | 
308 ms: 1.25x faster (-20%)  | 
350 ms: 1.11x faster (-10%)  | 
xml_etree_process  | 
338 ms  | 
263 ms: 1.28x faster (-22%)  | 
290 ms: 1.16x faster (-14%)  | 
Optimized Pythonは上記のどの項目においても公式のPythonイメージより高速に動作することがわかりました。 ただ、システム(OS)のPythonとほぼ同じような速度なので、元からシステムのPythonを使ってる場合には恩恵はなさそうです。
既にDockerでPythonを使っており、下記のような記述の場合は
FROM python:3.6.3
下記のように書き換えるだけでPythonの処理が高速になる可能性があります。
FROM revolutionsystems/python:3.6.3-wee-optimized-lto
DockerでPythonを使っていて、少しでも高速化したい場合には試してみてはいかがでしょうか。
Footnotes
2017年12月1日現在、最新情報はDocker Hubのタグを参照 https://hub.docker.com/r/revolutionsystems/python/tags/
Copyright © 2020 driller
Powered by miyadaiku