Release the GIL during evaluation, and decide on free-threaded (cp314t) support
还没有人认领这个 Issue。
评估
- 难度
- 5/5
- 预计耗时
- 一周以上
- 新手友好度
- 42/100
调研方向
从 evaluate() 和 Program.execute() 开始,然后运行 compile_execute_benchmark.py,以根据所述阈值测量 detach/attach 开销。审查 Context、共享的 stdlib Env 和 per-Context cache 的 free-threaded 安全性,并检查 maturin-action CI matrix。完成的标准是:并发评估有测试覆盖,GIL-release 选择经过基准测试,并且在支持的情况下包含 cp314t wheels。
由索引模型根据 Issue 内容生成。
描述
Problem
evaluate() and Program.execute() hold the GIL for the entire Rust-side evaluation. A Python program that evaluates CEL from several threads therefore serialises on the interpreter even though the work is pure Rust once the context has been converted. This matters for the policy-engine style of use (many rules × many requests) that the README leads with.
Proposal
- Release the GIL around
program.execute()withpy.detach(|| ...)(PyO3 0.29's spelling ofallow_threads). The pieces already have the right bounds:cel::Programis a plain AST,cel::Context<'static>isSend + Sync(itsVal,FunctionandVariableResolvertraits all require it), and the Python-callback wrappers already do their ownPython::attach, so a callback simply re-acquires the GIL when it runs. Conversion of the result back to Python happens after re-attaching. - Measure the fixed cost. Detach/attach is on the order of tens of nanoseconds, but a trivial
x + yexecutes in ~0.15 µs, so unconditional detaching could be a visible relative slowdown for tiny expressions while being a large absolute win for anything heavier or for multi-threaded callers. Options, in order of preference:- detach unconditionally if the overhead measures under ~10% on the
compile_execute_benchmark.pycases; - otherwise detach only when the context has no Python functions and no resolver (that's when the evaluation cannot need the GIL), which is cheap to know from the
Context; - an explicit
execute(ctx, release_gil=...)knob is a last resort.
- detach unconditionally if the overhead measures under ~10% on the
- Free-threaded Python. PyO3 0.29 supports the free-threaded build when the module opts in with
#[pymodule(gil_used = false)]. Before doing that, audit:Contextmutators are&mut self(PyO3's borrow checker turns concurrent mutation into an error rather than a data race), the shared stdlibEnvis aLazyLock, and the per-Contextcache proposed in the Context-reuse PR is behind aMutex. Then addcp314twheels to the CI matrix (maturin-action needs the interpreter listed explicitly;--find-interpreterwon't pick it up).
Non-goals
Context itself is documented as not thread-safe for concurrent mutation; that stays. Concurrent evaluation against a shared Context is already fine and is now pinned by tests.
- 主要语言
- Python
- 星标
- 43
- 派生
- 4
- 平均合并
- 12 小时 37 分钟
- 30 天内合并 PR
- 11
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
hardbyte/python-common-expression-language 的其他 Issue
-
enhancement
难度 2/5 1-3 小时 新手友好度 78/100
-
enhancement
难度 4/5 3-5 天 新手友好度 45/100
-
难度 5/5 一周以上 新手友好度 35/100
-
enhancement
难度 4/5 3-5 天 新手友好度 48/100
-
enhancement
难度 5/5 一周以上 新手友好度 45/100
查看 hardbyte/python-common-expression-language 的全部 Issue
相似的 Issue
-
bug
难度 2/5 1-3 小时 新手友好度 75/100
stephrobert/dsoxlab#238 ·
-
难度 2/5 1-3 小时 新手友好度 75/100
-
难度 2/5 1-3 小时 新手友好度 75/100
sublimehq/package_control#1780 ·
-
难度 2/5 1-3 小时 新手友好度 65/100
-
难度 2/5 1-3 小时 新手友好度 70/100
nwg-piotr/nwg-displays#145 ·