Slow functions calls for C-coded functions, accepting positional-or-kwarg argument vs positional-only
還沒有人認領這個 Issue。
- 主要語言
- Python
- 星號
- 77.2k
- 分支
- 36k
- PR 合併指標
- PR 指標待擷取
描述
Bug report
Bug description:
I don't see measurable difference on pure-Python level, e.g. for
# a.py
import pyperf
def f1(x):
return 1
def f2(x, /):
return 1
runner = pyperf.Runner()
runner.bench_func("f1(1)", f1, 1)
runner.bench_func("f2(1)", f2, 1)
I got on 3.13:
$ python a.py -q
f1(1): Mean +- std dev: 233 ns +- 2 ns
f2(1): Mean +- std dev: 232 ns +- 2 ns
But for functions, implemented in C, using the Argument Clinic - the difference is bigger:
$ python bench.py -q -o patch.json
isfinite(1.0): Mean +- std dev: 152 ns +- 1 ns
$ git checkout master && make -s
Checked 114 modules (35 built-in, 78 shared, 1 n/a on linux-x86_64, 0 disabled, 0 missing, 0 failed on import)
$ python bench.py -q -o ref.json
isfinite(1.0): Mean +- std dev: 136 ns +- 1 ns
| Benchmark | ref | patch |
|---|---|---|
| isfinite(1.0) | 136 ns | 152 ns: 1.12x slower |
(In the second version - the math.isfinite() accept also keyword argument x)
a patch
(run ./python Tools/clinic/clinic.py Modules/mathmodule.c !)
diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c
index 7c2a421dd6..e33281ac8b 100644
--- a/Modules/mathmodule.c
+++ b/Modules/mathmodule.c
@@ -3156,14 +3156,13 @@ math_radians_impl(PyObject *module, double x)
math.isfinite
x: double
- /
Return True if x is neither an infinity nor a NaN, and False otherwise.
[clinic start generated code]*/
static PyObject *
math_isfinite_impl(PyObject *module, double x)
-/*[clinic end generated code: output=8ba1f396440c9901 input=46967d254812e54a]*/
+/*[clinic end generated code: output=8ba1f396440c9901 input=a47ad6e72998b81d]*/
{
return PyBool_FromLong((long)isfinite(x));
}
This performance penalty affects API decisions (e.g. https://github.com/python/cpython/pull/131886) and that looks as a bug.
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Linked PRs
- gh-136732
- gh-137202
貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
研究方向
從 bench.py 中的 benchmark 和 pyperf 範例開始,比較 positional-only 和 positional-or-keyword 形式下的 math.isfinite(1.0)。檢查 Modules/mathmodule.c 以及由 Tools/clinic/clinic.py 產生的 Argument Clinic 輸出;當以 C 撰寫的呼叫不再出現回報的迴歸,同時 benchmark 和 API 行為維持正確時,即表示完成。
由索引模型根據 Issue 內容生成。
評估
- 技術堆疊
- c, python
- 領域
- performance
- Issue 類型
- 缺陷
- 難度
- 4/5
- 預估耗時
- 3-5 天
- 活躍度
- 停滯
- 描述清晰度
- 基本清楚
- 新手友好度
- 30/100