mypy 冷启动检查很慢怎么通过远程缓存加速?
【免费下载链接】mypyOptional static typing for Python项目地址: https://gitcode.com/GitHub_Trending/my/mypy
mypy 默认是增量类型检查,会复用上一次运行的缓存。但“冷启动”场景下这套机制帮不上忙:比如你基于一个比上次 mypy 运行目标新得多的提交建了新分支,或者刚 rebase 过本地分支,此时本地.mypy_cache与目标提交差距很大,mypy 几乎要重新处理每个源文件。mypy 官方文档给出的针对性方案是远程缓存(remote cache):把 CI 构建产出的增量缓存按提交 ID 存到一个共享仓库,开发者本地运行时先按 merge base 提交下载对应缓存填充本地.mypy_cache,再跑一次普通增量构建。文档说明,在大代码库中远程缓存有时能让 mypy 运行提速 10 倍以上(docs/source/additional_features.rst)。
需要明确两个前提(均来自 docs/source/additional_features.rst):
- mypy 本身不包含远程缓存所需的全部组件,你需要自己做 CI 或构建系统的简单集成,把 mypy 配置成使用远程缓存;
- 讨论假设你已经为目标 mypy 构建配好了 CI 系统,并且使用中央 git 仓库。
文档同时给出规模参考:项目代码量达到约 10 万行以上时,可以考虑配置远程缓存(docs/source/existing_code.rst);docs/source/common_issues.rst 中“Mypy runs are slow”一节的结论是:用 daemon 加速重复的增量运行,而远程缓存让冷的mypy 运行快上数倍——两者解决的正是本文的冷启动问题。
远程缓存的三块组件
文档把整套方案拆成三个部分:
- 缓存文件共享仓库:能上传 mypy 缓存文件、并能按 commit ID 下载缓存的仓库。简单做法是把
.mypy_cache目录(mypy 缓存数据所在目录)打成压缩包,作为 CI 构建的可下载build artifact(取决于你的 CI 系统能力);也可以上传到 web server 或 S3。 - 上传缓存的 CI 构建:对每个运行 CI 构建的提交,把 mypy 增量缓存文件上传到共享仓库。
- 开发者用的 mypy 包装脚本:本地开发时用它代替直接调用 mypy,先填充本地
.mypy_cache再跑增量构建。
下面按文档给出的顺序搭这三块。
第一步:CI 构建中产出并上传缓存
CI 脚本按文档描述的流程工作(docs/source/additional_features.rst):
- 正常运行 mypy——这会在
.mypy_cache目录下生成缓存数据; - 把
.mypy_cache目录打成 tarball; - 确定当前 git master 分支的 commit ID(文档示例用
git rev-parse HEAD); - 以 commit ID 派生出的名称把 tarball 上传到共享仓库。
也就是说,缓存的“寻址键”是 commit ID:CI 每个跑过的提交都留下一份按该提交命名的缓存包,后面所有本地运行都按提交去取。
第二步:本地包装脚本——先定位 merge base,再下载缓存
包装脚本用于开发者在本地开发时运行 mypy,逻辑是:先把共享仓库中的缓存数据解压填充到本地.mypy_cache,让 mypy 从一个“新鲜”的.mypy_cache起步,然后正常执行 mypy。
脚本里最关键的一步是确定本地开发分支所基于的最近中央仓库提交(按惯例是 git 的origin/master分支),文档给出的典型 git 做法是:
git merge-base HEAD origin/master拿到这个 merge base 的 commit ID 后,脚本据此从共享仓库下载对应提交的缓存数据(即.mypy_cache目录内容),解压后运行 mypy。文档原话是“最后,脚本正常运行 mypy。就这样!”
第三步:验证冷启动是否变快了
判断方法直接来自 daemon 文档(docs/source/mypy_daemon.rst):dmypy的初始运行“会处理全部代码,可能花一段时间”,而“你可以使用远程缓存来加速初始运行。如果你有大代码库,提速可以非常明显”。因此可核对的成功条件是:配置远程缓存后,基于干净/重置的.mypy_cache的第一次 mypy(或dmypy check)运行耗时明显低于冷缓存时的耗时。如果 merge base 提交太新,缓存数据可能还没构建出来,此时脚本应能回退到普通增量构建(见下文“限制”)。
可选分支:与 mypy daemon 配合
如果你用dmypydaemon 做开发期检查,远程缓存可以直接加速“启动或重启 daemon 后的第一次dmypy check”(docs/source/additional_features.rst)。但 daemon 对缓存文件有额外要求:它需要默认不包含的细粒度依赖数据,所以要在 CI 构建中使用--cache-fine-grained选项:
mypy --cache-fine-grained <args...>该标志会把 daemon 需要的额外信息写进缓存。消费端相应地要在dmypy start或dmypy restart时使用--use-fine-grained-cache选项:
dmypy start -- --use-fine-grained-cache <options...>这样第一次dmypy check就能利用缓存信息避免处理整个程序,应该明显更快。<args...>/<options...>处替换为你原有的 mypy 参数。
顺手可做的加速项:faster-cache 额外依赖
docs/source/common_issues.rst 提到,从 mypy 1.13 起,mypy 允许用 orjson 库代替标准库 json 来处理缓存以提升性能。安装方式是通过faster-cacheextra 确保 orjson 存在:
python3 -m pip install -U mypy[faster-cache]文档还说明 mypy 未来可能默认依赖 orjson。这条改动不依赖远程缓存,可以单独先做。
限制与文档给出的细化建议
文档列出的可选细化(“Refinements”,对几十万行以上的代码库尤其有用),每一条都对应一个真实边界:
- merge base 未变化时:包装脚本无需重新下载缓存,直接复用已有本地缓存数据更好。
- 分支切换:如果切到一个已下载过缓存的已有本地分支,可以继续用现有缓存而不是重新下载。文档建议用
--cache-dir选项(见 docs/source/command_line.rst)为不同本地分支维护多个本地缓存目录;--cache-dir默认指向当前目录下.mypy_cache,设置该标志会覆盖MYPY_CACHE_DIR环境变量。 - 最新 master 提交可能没有缓存:由于构建缓存文件必然存在延迟,如果本地分支基于非常新的 master 提交,该提交的远程缓存可能尚未可用。文档建议可以查找最近若干 master 提交的缓存(例如最近 5 个),使用其中最新可用的一份。
- 远程缓存不可访问时(例如从公网访问):脚本应回退到普通增量构建。
- 用 daemon 时:merge base 或本地分支变化后建议重启 daemon,避免增量构建处理大量变更——这可能比“下载缓存 + 重启 daemon”慢得多。
- CI 自身:也可以让 CI 构建使用远程缓存来加速 CI,特别是每次 CI 都从全新状态开始、拿不到上次构建缓存的情形。文档同时建议仍然运行一次完整的非增量 mypy 构建来生成缓存数据,因为反复增量更新缓存长时间下来可能产生漂移(可能是缓存问题所致)。
另外注意版本约束:mypy 默认会忽略其他 mypy 版本生成的缓存数据,--skip-version-check会禁用这一行为(docs/source/command_line.rst)。因此共享仓库中的缓存与本地 mypy 版本不一致时会被自动忽略,这属于预期行为,不需要“修复”。
小结
按本文路径做完后,你应该得到:CI 上每个提交对应一份按 commit ID 命名的.mypy_cache压缩包;本地包装脚本通过git merge-base HEAD origin/master定位基础提交、下载并解压缓存后运行 mypy;冷缓存下第一次 mypy /dmypy check的耗时明显下降。若 merge base 提交过于新或远程缓存不可达,回退为普通增量构建,不影响正确性。相关文档:docs/source/additional_features.rst、docs/source/common_issues.rst、docs/source/mypy_daemon.rst、docs/source/command_line.rst。
【免费下载链接】mypyOptional static typing for Python项目地址: https://gitcode.com/GitHub_Trending/my/mypy
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考