こんにちは、Habr!
数ヶ月前に学んだ素晴らしいイベントについてお話ししたいと思います。人気のあるPythonユーティリティの1つが、Pythonから直接コンパイルされたバイナリとして1年以上配布されていることがわかりました。そして、それはいくつかのことで陳腐梱包についてではありませんpyInstallerのが、正直な程度、控え・オブ・タイム全体のpythonパッケージのコンパイル。私と同じくらい驚いたら、猫へようこそ。
このイベントが本当に素晴らしいと思う理由を説明しましょう。コンパイルには2つのタイプがあります。 プログラムを開始する前にすべてのコードをコンパイルするAhead-of-time(AOT)と、プログラムの実行中に必要なプロセッサアーキテクチャ用にプログラムを直接コンパイルするJust in Timeコンパイラ(JIT)です。 。2番目のケースでは、プログラムの最初の起動は仮想マシンまたはインタープリターによって実行されます。
人気のあるプログラミング言語をコンパイルタイプ別にグループ化すると、次のリストが得られます:
事前コンパイラ:C、C ++、Rust、Kotlin、Nim、D、Go、Dart;
ジャストインタイムコンパイラ:Lua、C#、Groovy、Dart。
Pythonにはすぐに使えるJITコンパイラはありませんが、そのような機会を提供する個別のライブラリは長い間存在していました。
, : . : Kotlin JIT JavaVM, AOT Kotlin/Native. Dart ( 2). A JIT-, .
, , . .
JIT , . JIT . AOT , ? , .
, , . mypy - python-.
2019 , . — mypyc. , “ 4 Python-” mypy ( : 1, 2, 3). mypyc: mypy python- Dropbox, , . , : go cython. — AOT python-.
, mypy , . mypy “” python, , mypyc .
, , python-. Python c 3.4 , mypy . , python , AOT . , mypyc !
bubble_sort
“”. lib.py:
def bubble_sort(data):
n = len(data)
for i in range(n - 1):
for j in range(n - i - 1):
if data[j] > data[j + 1]:
buff = data[j]
data[j] = data[j + 1]
data[j + 1] = buff
return data
, mypyc . , mypyc. , mypy, mypyc ! mypyc, :
> mypyc lib.py
:
.mypy_cache
— mypy , mypyc mypy AST;
build
— ;
lib.cpython-38-x86_64-linux-gnu.so
— . CPython Extension.
CPython Extension — CPython , /C++. , CPython lib. , python.
:
python ;
.so , mypyc gcc (gcc python-dev ).
lib.cpython-38-x86_64-linux-gnu.so
lib.py , .
. main.py :
import lib
data = lib.bubble_sort(list(range(5000, 0, -1)))
assert data == list(range(1, 5001))
:
|
|
real 5.68 user 5.60 sys 0.01 |
real 2.78 user 2.73 sys 0.01 |
(~ 2 ), , . .
“ ”, . , .
sum(a, b)
:
def sum(a, b):
return a + b
:
int sum(int a, int b) {
return a + b;
}
c ( ):
PyObject *CPyDef_sum(PyObject *cpy_r_a, PyObject *cpy_r_b){
return PyNumber_Add(cpy_r_a, cpy_r_b);
}
, . -, , PyObject, CPython . , , : , , , , . mypyc?
, : CPython . PyNumber_Add — Python, , Python .
CPython c Extension :
— - sum A, B;
— , , A + B;
— ;
— , - .
: , , .
, , , mypyc , .
sum(a: int, b: int)
, python, , , . , . , CPython - Extension. ?
, , , , CPython. mypyc , . mypyc , , sum. , , . , -, :
def sum(a: int, b: int):
return a + b
C ( ):
PyObject *CPyDef_sum(CPyTagged cpy_r_a, CPyTagged cpy_r_b) {
CPyTagged cpy_r_r0;
PyObject *cpy_r_r1;
cpy_r_r0 = CPyTagged_Add(cpy_r_a, cpy_r_b);
cpy_r_r1 = CPyTagged_StealAsObject(cpy_r_r0);
return cpy_r_r1;
}
, : , , . , .
CPyDef_sum PyObject, CPyTagged. int, CPython, mypyc, . , sum int .
CPyTaggetAdd PyNumber_Add. mypyc. CPyTaggetAdd, , a b, int, , :
if (likely(CPyTagged_CheckShort(left) && CPyTagged_CheckShort(right))) {
CPyTagged sum = left + right;
if (likely(!CPyTagged_IsAddOverflow(sum, left, right))) {
return sum;
}
}
, CPython - Extension :
— - sum A, B;
— , .
bubble_sort(data: List[int])
, . , data:
def bubble_sort(data: List[int]):
…
:
|
, |
|
real 5.68 user 5.60 sys 0.01 |
real 2.78 user 2.73 sys 0.01 |
real 1.32 user 1.30 sys 0.01 |
, , , !
mypyc
, , . mypyc : , , , mypy. mypy . python-, , .
, , :
;
monkey patching;
Mypy , .
. , , abc. , . , gcc , , , . , , 20 % , .
Nuitka
, . Nuitka . , Nuitka Python ++ , Python Extension. , CPython libpython.
Nuitka , . mypy .
, mypy : , “ ”, PyCharm . , mypy. , . , python. mypy — , . , CPython , , . (, mypyc ). , mypyc , , , - , mypyc, , , mypy.
P.S.
, python, . , mypyc, , , .
UPD
, python - Cython, python ( cython-). cython , (real 1.82) mypyc . .