You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python 3.11.1中all()/any()性能较3.10.9下降问题咨询

Python 3.11.1中all()/any()性能下降的问题

我发现Python 3.11.1里all()和any()的实现比Python 3.10.9分别慢30%和23%,但单独判断item["id"] == match_data["id"]时,3.11.1反而快3%。以下是测试代码及结果,想请教该性能差异的原因:

测试代码

import timeit
from functools import partial
import platform


def find_by_keys(
    keys: list[str],
    table: list[dict[str, str | int]],
    match_data: dict[str, str | int],
) -> dict[str, str | int] | None:
    for item in table:
        if all(item[k] == match_data[k] for k in keys):   # 30% slower on 3.11
        # if any(item[k] == match_data[k] for k in keys):   # 23% slower on 3.11
        # if item["id"] == match_data["id"]:   # 3% faster on 3.11
            return item
    return None


def main():
    keys: list[str] = ["id", "key_1", "key_2"]
    table: list[dict[str, str | int]] = [
        {
            "id": i,
            "key_1": "val_1",
            "key_2": "val_2",
        }
        for i in range(1, 5001)
    ]
    match_data: dict[str, str | int] = {
        "id": 3000,
        "key_1": "val_1",
        "key_2": "val_2",
    }

    # Note: used repeat=50000 for all() calls, otherwise used repeat=500000
    timeit_output = timeit.repeat(
        partial(find_by_keys, keys, table, match_data),
        repeat=50000,
        number=1
    )

    average_time = sum(timeit_output) / len(timeit_output)
    best_time = min(timeit_output)
    tps_output = 1 / average_time

    print(f"Python version = {platform.python_version()}")
    print(f"Average time = {average_time}")
    print(f"Best time = {best_time}")
    print(f"Average transactions per second = {tps_output}")


if __name__ == "__main__":
    main()

测试结果

Python 3.10.9输出

Python version = 3.10.9
Average time = 0.0008256170657486655
Best time = 0.0007106999401003122
Average transactions per second = 1211.2152733824669

Python 3.11.1输出

Python version = 3.11.1
Average time = 0.0011819988898839802
Best time = 0.001033599954098463
Average transactions per second = 846.0244832363215

性能差异的原因分析

  • 生成器迭代的固定开销:Python 3.11的核心优化是更快的字节码解释器,但all()/any()依赖生成器表达式作为迭代源。生成器的创建、挂起和恢复操作在3.11中引入了额外的固定开销,这种开销在短迭代(比如仅3个元素的keys列表)场景下占比极高,抵消了解释器的整体优化收益。而单次字典键值比较无需生成器的迭代协议,能直接享受到3.11的解释器提速。
  • all()/any()的内部实现调整:3.11对all()和any()的底层逻辑可能做了调整,比如增加了类型检查或兼容性处理步骤。这些额外操作在处理短序列时,单位元素的开销被放大,导致整体性能不如3.10。
  • 短迭代场景的开销放大效应:当迭代序列长度极短时,迭代器的启动和管理开销占总耗时的比例远高于实际元素处理的耗时。3.11中这种迭代器相关的固定开销比3.10更高,而单次比较没有这部分开销,所以呈现出相反的性能表现。

内容的提问来源于stack exchange,提问作者Onlooker2186

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 17:35:12