云服务器价格_云数据库_云主机【优惠】最新活动-搜集站云资讯

消息队列_怎么设置代理服务器_年度促销

小七 141 0

基于Bazel的数据链快速并行测试

Databricks Developer Tools团队最近完成了一个项目,该项目极大地加快了我们许多工程师的拉请求(pull request,PR)验证工作流程:通过大规模并行化我们的测试,以前花了~3小时的验证运行现在在~40分钟内完成。这篇博客文章将深入探讨我们是如何利用Bazel构建工具来实现对我们许多工程师日常工作流程的极大加速。幕后故事Databricks代码库大致分为两个大的代码库:运行时代码库:我们基于apachespark和Delta-Lake的云优化计算引擎,具有额外的可伸缩性、可靠性和性能增强。Universe代码库,包含我们所有的服务、UI、部署配置、自动化:将核心计算引擎转换为统一分析平台所需的一切。由于历史原因,这两个代码库是非常不同的:不同的构建工具,不同的测试基础设施,不同的工程师在每一个代码库上工作。但他们两个一开始使用SBT构建的Scala也出现了分歧:Universe在2016年改用Bazel,完全取消了SBT的构建运行时仍然是SBT和一些外围工具(用Python编写)的混合体,以支持测试代码库的非Scala部分验证时间从2019年到2016年,从2小时到2016年。在Databricks,我们将所有的历史CI数据保存在三角洲湖中,使用Databricks笔记本电脑可以很容易地分析这些数据:选择内部版本号,平均值(持续时间/秒)/60秒,总和(持续时间?毫秒)/1000/60作为测试?cpu?分钟,DATE_TRUNC("周",第一个(日期))作为日期来自塔霍市。`/home/jenkins/test_results_加入`其中name="运行时sbt构建"按内部版本标识分组如您所见,我们设法将验证运行所用的总时间(build_duration,蓝色)保持在2-3小时左右,即使运行测试本身所用的总时间(test_duration,橙色)已经增长。这种差异来自于并行运行多个套件,这意味着每次验证运行所需的时间只有串行运行测试时的1/4。相比之下,使用Bazel构建和测试的Universe代码库的大小和复杂性相当,其验证套件的运行时间在30-60分钟之间。运行时验证套件的缓慢运行一直是困扰Databricks工程师的一大难题。在我们的定期开发人员生产力调查中,年复一年地反复出现:等待Jenkins测试运行时PR需要很长时间。如果这至少可以部分并行化,那就太好了。2017测试pr时,测试不会并行运行,而且速度非常慢。2018让詹金斯在运行时测试我的PR需要等3个小时,结果一个不可靠的测试最终会毁了一切。2019在这24个月的时间里,各种各样的人至少花了整整6个月的时间来守住这条线。到目前为止,我们正在以3-4种方式并行运行测试,阻止了PR验证运行从膨胀到10小时以上,但仍然无法在3小时的等待中取得很大进展。并行运行时测试的问题我们不能取得更多进展的根本原因是缺乏测试隔离。许多测试都是在测试套件串行运行的时候编写的,并且假设这些测试很难并行运行:意外干扰:一些测试共享缓存或暂存文件夹。当它们并行运行时,它们会互相冲突,互相搅乱彼此归档。偶然依赖:一些测试隐含地依赖于其他测试在磁盘上留下缓存或临时文件夹的。当你走错了路先决条件文件会丢失。我们已经做了很多努力来缓解这些问题——分叉独立的进程,在不同的工作目录中运行套件,并为它们分配单独的暂存文件夹——但是故障的不确定性使得跟踪和修复它们变得不可能。我们曾经尝试配置SBT构建工具来运行容器内的测试,但是SBT的内部结构很复杂,似乎不适合这样的更改。巴泽尔当运行时验证套件给我们带来问题时,我们早就把Universe代码库和验证套件从SBT移到了Bazel,我们对此非常满意。Bazel基本上给你三个主要的东西:并行性:任何互不依赖的构建步骤都是并行执行的缓存:如果构建步骤的输入没有更改,则会重用输出。这个缓存甚至可以跨机器共享隔离:默认情况下,每个构建步骤都在一个隔离的"沙盒"环境中运行,只能访问您明确指定给它的文件这三个优点同样适用于编译代码和运行测试。虽然前两个属性为我们提供了在宇宙代码库中非常快速的构建时间,但最后一个属性同样重要:意外共享工作目录的测试将被分配到单独的文件夹中工作,不再冲突,并成功意外共享其他文件系统内容(工作目录之外的内容)的测试在100%的情况下都会失败实际上,Bazel将这些与构建相关的非确定性失败转化为保证成功或保证失败。这两个问题都比不确定的海森堡更容易处理!Bazelizing运行时我们决定为运行时代码库建立一个Bazel构建,并将我们的测试套件迁移到它上面。由于这需要一些时间,所以我们让Bazel测试套件与现有的SBT测试套件并排运行。随着Bazel构建的完整性增加,我们将测试从SBT套件一个一个地移动到Bazel套件。调整SBT以跳过Bazel所知道的测试,这只是Bazel查询的一个问题。编译/运行/测试Scala代码、处理Protobuf、JVM类路径等的所有机制都直接继承自我们的busel配置。我们移植到Bazel的第一批~1200/1800个测试套件已经出厂。这留下了600个不同故障的长尾。主要主题是:损坏的测试,由于SBT构建的某些属性而完全是意外通过的(例如,一个测试只在太平洋时区运行时通过,如果工作目录路径的字符太少,另一个测试失败)Bazel和SBT之间Maven Central对第三方依赖的不同解析,导致类路径上的jar不同隐式文件依赖性:Bazel的隔离意味着您必须向它提供测试所需的所有文件的详尽列表,并且除非您事先声明,否则不会让您访问整个文件系统来获取东西共享文件夹(如~/.ivy2/cache)上的冲突Bazel配置中的错误:有时我们只是把模块间依赖项列表弄错了,遗漏了环境变量,JVM标志等等。Bazel本身的缺陷:事实证明Bazel非常不喜欢您将文件夹命名为external/,但通过将其重命名为其他名称,很容易解决这个问题!其中一些问题很难调试,导致了大量代码库中不熟悉部分的神秘故障。但事实上,故障是可重复的,这意味着修复它们实际上是可能的!只是时间问题。下面的图表显示了旧的/SBT和新的/Bazel PRvalidation套件中的测试数量,我们可以清楚地看到测试从一个迁移到另一个:以成功作为(选择DATE_TRUNC("WEEK",DATE),count(distinct(class_name))作为num来自塔霍市。`/home/jenkins/test_results_加入`按日期分组),bazel AS(SELECT*FROM successions WHERE),sbt AS(从成功中选择*其中name="runtime sbt build")选择sbt编号作为sbt_num,巴泽尔。num作为bazel_num,sbt.日期作为日期来自bazel完全外部连接sbt打开sbt.日期= bazel.日期总而言之,花了大约2个月的时间烧毁了600个故障。性能数字当我们把测试从SBT移到Bazel时,我们可以看到SBT测试时间下降,Bazel测试时间增加。以下是Databricks笔记本上的数字:以成功作为(选择DATE_TRUNC("WEEK",timestamp)作为day,name,AVG(dur?秒)/60作为dur来自tahoe。`/home/jenkins/build_results`按日期分组("周",时间戳),名称),bazel AS(选择day,dur FROM successions WHERE),sbt AS(选择day,dur FROM successions,其中name="runtime sbt build")选择标准时间就像《华尔街日报》,巴泽尔杜尔就像巴泽尔·沃尔丘分钟,标准日就像白天一样来自bazel完全外部连接sbt打开标准日= 集市日总的来说,在整个项目过程中,SBT验证套件的时间从大约180分钟下降到了约30分钟:在转移了所有测试之后,该构建中只剩下一个完整的编译,以及一些碰巧与SBT构建工具相关的杂项lint规则。同时,我们看到Bazel的构建从0增长到结束大约需要40分钟。考虑到前10分钟左右只是编译(在Bazel和SBT之间没有变化),我们看到并行性提高了6倍,大约150分钟的SBT测试被压缩到Bazel下20分钟的测试。为了最好地利用Bazel增强的并行能力,我们在EC2(m5.24xlarge)上强大的96核机器上运行Bazel测试套件。而这些机器一直运行的成本很高(每台每年大约40000美元!),每个测试运行40分钟的持续时间为我们提供了每次运行2-3美元的成本:一个相当合理的货币成本!结论过去两年的运行时验证套件性能可以通过以下(有点长)Spark SQL查询可视化:%sql语言每个构建为(选择内部版本号,平均(持续时间\u秒)/60作为构建持续时间,总和(持续时间?毫秒)/1000/60作为测试持续时间,DATE_TRUNC("星期",第一个(日期))作为日期,第一个(n