Python|四年完成400万行Python代码检查,甚至顺手写了个编译器( 二 )
幸运的是 , 我们实现了一系列算法层面的改进 。 我们采用的第一项加速措施就是增量检查 。 其背后的思路非常简单:如果模块的所有依赖关系都与 mypy 运行前的状态毫无区别 , 那我们完全可以使用前一次运行的缓存数据获取依赖关系 , 意味着只需要类型检查修改了的文件及其依赖关系 。 mypy 则在此基础上更进一步:如果模块的外部接口没有改变 , mypy 甚至不需要重新检查导入该模块的其它模块 。
在对现有代码进行批量注释时 , 增量检查确实非常有用 , 因为其中往往涉及 mypy 的大量迭代运行 , 用以处理陆续插入且逐渐细化的类型 。 最初的 mypy 运行仍然相当缓慢 , 这是因为它需要处理大量依赖项 。 为此 , 我们实现了远程缓存 。 如果 mypy 检测到本地缓存可能已经过期 , mypy 将从集中存储库下载整个代码库的最新缓存快照 。 在此之后 , 它会以下载到的缓存为基础执行增量构建 。 这又进一步提高了性能表现 。
到 2016 年底 , Dropbox 公司已经有大约 42 万行 Python 完成了类型注释 。 很多用户都热衷于类型检查 , 而 mypy 的使用则在 Dropbox 各团队之间迅速传播 。
情况看起来相当不错 , 但距离真正的成功还有很长的路 。 我们开始定期进行内部用户调查 , 借以找出痛点 , 并确定需要优先考虑的工作(这种习惯直到今天也一直被保持下来) 。 其中 , 有两项请求始终排名最高:更大的类型检查覆盖范围以及更快的 mypy 运行速度 。 很明显 , 我们的性能与采用提升工作还没有全部完成 。 为此 , 我们还得在这两项任务上再多下点力气 。
文章插图
性能提升方法一:使用 mypy 守护进程
增量构建虽然提升了 mypy 的速度 , 但仍然没有达到顶峰 。 大量增量运行可能需要一分钟的处理时长 。 对于任何面对大型 Python 代码库的用户来讲 , 其中的原因相信并不难理解:循环导入 。
我们拥有数百个模块 , 模块相互间接导入 。 如果导入周期的任何文件发生变更 , 那么 mypy 就必须处理周期中的所有文件 , 同时还得处理在此周期内导入该模块的所有其它模块 。 其中最臭名昭著的循环就是“纠结(tangle)” , 它给 Dropbox 带来了很大麻烦 。 其中一度包含有数百个模块 , 众多测试级乃至产品级功能都要或直接或间接地将其导入 。
我们一直在考虑打理这种纠结无比的依赖关系 , 但却始终没有合适的方法着手进行 。 毕竟我们不熟悉的代码太多了 。 因此 , 我们想出了另一个办法——即使存在这种“纠结” , 我们同样可以提升 mypy 速度 。 答案就是 , 使用 mypy 守护进程 。 守护进程是一项服务器进程 , 负责执行两项非常重要的工作 。
首先 , 它将关于整体代码库的信息保存在内存中 , 这样每次 mypy 运行就不再需要加载数千条与所导入依赖项相对应的缓存数据 。 其次 , 它会跟踪函数与其构造之间的细粒度依赖关系 。 例如 , 如果函数 foo 调用函数 bar , 那么就存在一项从 bar 到 foo 的依赖关系 。 当文件发生变更时 , 守护程序会首先单独处理已经变更的文件;接下来 , 它会查找该文件中包含的外部可见变更 , 例如变更的函数签名 。 守护程序所采用的细粒度依赖项管理机制 , 能够确保只重新检查实际变更的那些函数——换言之 , 只检查极少数函数 。
- 融资|小影科技完成近4亿元C轮融资,已启动上市
- 出海|出海日报丨短视频生产服务商小影科技完成近4亿元 C 轮融资;华为成为俄罗斯在线出售智能手机的第一品牌
- 手机|新鲜评测:让手机变身电脑的显示器见过没?只用4步即可完成!
- 生产|短视频生产服务商“小影科技”完成近4亿元C轮融资
- 网络|大禹网络完成数亿元人民币A轮融资
- 海沧|厦门海沧转动卫浴行业发展引擎 今年前十个月完成工业产值62.3亿元
- 苏宁|苏宁易购旗下云网万店完成 60 亿元 A 轮融资
- 视频剪辑|提供视频剪辑工具,小影科技完成近 4 亿元 C 轮融资
- 融资|酒水外卖平台“酒小二”宣布完成A轮融资
- 运维|全栈智能业务运维服务商云智慧完成 D3 轮 6000 万美元融资