Python|四年完成400万行Python代码检查,甚至顺手写了个编译器( 三 )
实现上述目标当然是个巨大的挑战 , 因为我们最初的 mypy 实现方案只适合一次处理一个文件 。 但在实际需求发生变化之后——例如当某个类获得一个新的基类时 , 我们必须重新处理大量边缘情况 。 经过艰苦卓绝的努力与投入 , 我们成功将大部分增量运行缩短至几秒钟 。 这是一场伟大的胜利 , 至少在我们当事人看来相当伟大!
性能提升方法二:将 Python 编译为 C
配合之前提到的远程缓存 , mypy 守护进程几乎完全解决了增量类用例 , 工程师们只需要对少量文件进行迭代变更即可 。 但是 , 最差情况下的性能表现仍然远未达到最佳状态 。 进行一次彻底的 mypy build 可能需要 15 分钟 , 这样的结果当然无法令人满意 。 由于工程师们在不断编写新代码 , 并在现有代码当中添加类型注释 , 因此情况每周都在恶化 。 我们的用户渴望获得更高的性能 , 而我们也自然不能让大家失望 。
因此 , 我们决定延续 mypy 立项之初的重要想法——将 Python 编译为 C 。 遗憾的是 , Cython(一款现成的 Python 到 C 编译器)并不能提供任何显著的加速效果 , 因此我们决定从零开始编写编译器 。 由于 mypy 代码库(使用 Python 编写)已经全面完成类型注释 , 因此利用这些注释来加快速度自然是符合逻辑的选择 。 我构建了一套快速概念验证原型 , 其在各类微基准测试中将性能提升了 10 倍以上 。 我们的想法是将 Python 模块编译为 CPython C 扩展模块 , 并将类型注释转换为运行时类型检查(在运行时中通常被忽略的类型注释 , 仅供类型检查器使用) 。 我们开始着手将 mypy 实现由 Python 迁移至真正的静态类型语言 , 这恰好与 Python 的迁移思路完全匹配 。 (这种跨语言迁移正成为新的常态 , mypy 最初由 Alore 编写 , 但后来则转换为 Java/Python 自定义语法的混合体 。 )
对 CPython 扩展 API 的定位 , 是保持项目整体可管理性的关键所在 。 我们不需要实现虚拟机或者 mypy 所需要的任何库 。 此外 , 我们仍然可以利用一切原有 Python 生态系统与工具(例如 pytest) , 并能够在开发期间继续使用经过解释的 Python 代码 , 从而实现极快的编辑测试周期且不必等待编译过程 。
这款被我们命名为 mypyc 的编译器(因为它利用 mypy 作为前端来执行类型分析)非常成功 。 总体而言 , 我们在不使用缓存的前提下实现了大约 4 倍的运行性能提升 。 mypyc 项目的核心开发在小团队的推动之下用了大约 4 个月即告完成 , 团队成员包括 Michael Sullivan、Ivan Levkivskyi、Hugh Han 和我自己 。 很明显 , 这里的工作量远少于使用 C++ 或者 Go 完全重写 mypy , 相关影响也要小得多 。 我们希望 mypyc 最终能够被交付至 Dropbox 的其他工程师手上 , 供他们编译并加速自己的更多代码 。
在达成如此出色的性能提升效果的过程中 , 我们尝试了不少有趣的性能工程方法 。 编译器可以利用快速、低级 C 构造实现众多操作的加速 。 例如 , 对某个已编译函数的调用会被翻译成 C 函数调用 , 而后者要比调用解释函数快得多 。 另外 , 某些操作(例如字典查找)仍然会回退至常规的 CPython C API 调用 , 从而略微提升编译时的调用速度 。 总而言之 , 我们摆脱了解释带来的性能开销 , 从而稍稍改善了操作的速度表现 。
我们还进行了一系列分析工作 , 希望了解“慢速操作”中的普遍共性 。 有了这些数据 , 我们尝试调整 mypyc 为这些操作生成速度更快的 C 代码 , 或者利用更快的操作方式重写相关 Python 代码(有时候确实没什么好办法 , 只能硬着头皮重写) 。 后者通常要比在编译器中自动转换容易得多 , 不过从长远来看 , 我们更倾向于实现自动化转换 。 但还是要具体问题具体分析 , 有时候为了以最低的投入获得更大的性能提升 , 我们也会抄近路 。
文章插图
3、实操:检查 400 万行代码在完成上述工作后 , 还面临一个重要挑战(也是 mypy 用户调查中排名第二的重要要求)就是提升类型检查的覆盖范围 。 我们尝试了多种方法以实现这项目标:从有机增长 , 到专注于 mypy 团队的手动调整 , 再到静态与动态自动化类型推理等 。 最后 , 我们发现其中并不存在简单的实现策略 , 但我们将多种方法结合起来 , 从而显著提高了能够在代码库中实现的快速注释工作量 。
结果就是 , 我们在最大的 Python 库(后端代码)中的注释行数在大约三年之内增长至近 400 万行 , 这些全都迁移成了静态类型代码 。 mypy 现在支持多种覆盖报告 , 能够帮助我们轻松跟踪相关进度 。 具体来讲 , 我们可以报告各类不够明确的类型来源——例如在注释中使用的显式、未经检查的类型 , 或者未进行类型注释的已导入第三方库等 。 为了在 Dropbox 当中改善类型检查精度 , 我们还在中央 Python 类型库中为不少流行的开源库提供经过针对性改进的类型定义(即 stub 文件) 。
- 融资|小影科技完成近4亿元C轮融资,已启动上市
- 出海|出海日报丨短视频生产服务商小影科技完成近4亿元 C 轮融资;华为成为俄罗斯在线出售智能手机的第一品牌
- 手机|新鲜评测:让手机变身电脑的显示器见过没?只用4步即可完成!
- 生产|短视频生产服务商“小影科技”完成近4亿元C轮融资
- 网络|大禹网络完成数亿元人民币A轮融资
- 海沧|厦门海沧转动卫浴行业发展引擎 今年前十个月完成工业产值62.3亿元
- 苏宁|苏宁易购旗下云网万店完成 60 亿元 A 轮融资
- 视频剪辑|提供视频剪辑工具,小影科技完成近 4 亿元 C 轮融资
- 融资|酒水外卖平台“酒小二”宣布完成A轮融资
- 运维|全栈智能业务运维服务商云智慧完成 D3 轮 6000 万美元融资