bazel构建原理

news2024/11/17 19:35:17

调度模型

传统构建系统有很多是基于任务的,例如 Ant,Maven,Gradle。用户可以自定义"任务"(Task),例如执行一段 shell 脚本。用户配置它们的依赖关系,构建系统则按照顺序调度。

基于 Task 的调度模型

这种模式对使用者很友好,他可以专注任务的定义,而不用关心复杂的调度逻辑。构建系统通常给予任务制定者极大的"权利",比如 Gradle 允许用户用 Java 代码编写任务,原则上可以做任何事。

如果一个任务,在输入条件不变的情况下,永远输出相同的结果,我们就认为这个任务是"封闭"(Hermeticity) 的。构建系统可以利用封闭性提升构建效率,例如第二次构建时,跳过某些输入没变的 Task,这种方式也称为 增量构建

不满足封闭性的任务,则会导致增量构建失效,例如 Task 访问某个互联网资源,或者 Task 在执行时依赖随机数或时间戳这样的动态特征,这些都会导致多次执行 Task 得到不同的结果。

Bazel 采用了不同的调度模型,它是基于目标Target【制品 (Artifact) 的】。Bazel 官方定义了一些规则 (rule),用于构建某些特定产物,例如 c++ 的 library 或者 go 语言的 package,用户配置和调用这些规则。他仅仅需要告诉 Bazel 要构建什么 target,而由 Bazel 来决定如何构建它。

规则由官方和可信赖第三方维护,规则产生的任务,满足封闭性需求,这使得用户可以信赖系统的增量构建能力。

bazel基于 Target 的调度模型如下图所示:

基于 Target 的调度模型

File 表示原始文件,Target 表示构建时生成的文件。当用户告诉 Bazel 要构建某个 Target 的时候,Bazel 会分析这个文件如何构建(构建动作定义为 Action,和其他构建系统的 Task 大同小异),如果 Target 依赖了其他 Target,Bazel 会进一步分析依赖的 Target 又是如何构建生成的,这样一层层分析下去,最终绘制出完整的执行计划。

并行编译

Bazel 精准的知道每个 Action 依赖哪些文件,这使得没有相互依赖关系的 Action 可以并行执行,而不用担心竞争问题。基于任务的构建系统则存在这样的问题:

基于任务的构建系统存在竞争问题

两个 Task 都会向同一个文件写一行字符串,这就造成两个 Task 的执行顺序会影响最终的结果。要想得到稳定的结果,就需要定义这两个 Task 之间的依赖关系。

Bazel 的 Action 由构建系统本身设计,更加安全,也不会出现类似的竞争问题。因此我们可以充分利用多核 CPU 的特性,让 Action 并行执行。

通常我们采用 CPU 逻辑核心数作为 Action 执行的并发度,如果开启了远端执行 (后面会提到),则可以开启更高的并发度。

增量编译

Bazel 将构建拆分为独立的步骤,这些步骤称为操作(Action)。每项操作都有输入、输出名称、命令行和环境变量。系统会为每个操作明确声明所需的输入和预期输出。

对 Bazel 来说,每个 Target 的构建过程,都对应若干 Action 的执行。Action 的执行本质上就是"输入文件 + 编译命令 + 环境信息 = 输出文件"的过程。

Action 的描述

如果本地文件系统保留着上一次构建的 outputs,此时 Bazel 只需要分析 inputs, commands 和 envs 和上次相比有没有改变,没有改变就直接跳过该 Action 的执行。

这对于本地开发非常有用,如果你只修改了少量代码,Bazel 会自动分析哪些 Action 的 inputs 发生了变化,并只构建这些 Action,整体的构建时间会非常快。

不过增量构建并不是 Bazel 独有的能力,大部分的构建系统都具备。但对于几万个文件的大型工程,如果不修改一行代码,只有 Bazel 能在一秒以内构建完毕,其他系统都至少需要几十秒的时间,这简直就是 降维打击 了。

Bazel 是如何做到的呢?

首先,Bazel 采用了 Client/Server 架构,当用户键入 bazel build 命令时,调用的是 bazel 的 client 工具,而 client 会拉起 server,并通过 grpc 协议将请求 (buildRequest) 发送给它。由 server 负责配置的加载,ActionGraph 的生成和执行。

Bazel 的 C/S 架构

构建结束后,Server 并不会立即销毁,而 ActionGraph 也会一直保存在内存中。当用户第二次发起构建时,Bazel 会检测工作空间的哪些文件发生了改变,并更新 ActionGraph。如果没有文件改变,就会直接复用上一次的 ActionGraph 进行分析。

这个分析过程完全在内存中完成,所以如果整个工程无需重新构建,即便是几万个 Action,也能在一秒以内分析完毕。而其他系统,至少需要花费几十秒的时间来重新构建 ActionGraph。

本文属于如下文章中的子章节

bazel学习系列章节汇总_m0_74043383的博客-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/962919.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

揭秘亚马逊Amazon测评,掌握细节和技巧,提升产品销量和评论数量

亚马逊是全球最大的跨境电商平台,拥有全球65个国家的几十个网站。对于跨境卖家来说,亚马逊是最值得选择的平台之一。 亚马逊的八大站点分别是美国、加拿大、墨西哥、欧洲、澳大利亚、日本、中东和巴西。 美国站点是全球最大的零售市场,拥有…

区块链实验室(18) - 用FISCO BCOS架设1个无标度网络

FISCO技术文档提供1个4节点的网络案例,这4个节点构成1个强连通图。强连通图在现实中通常是不存在的。 本文用FISCO架设1个网络,该网络由100个节点构成1个无标度(scale free)网络,如下图所示。 1 用FISCO工具构建1个100节点的初始网络 FISCO提…

Jenkins java8安装版本安装

一、首先准备Jenkins、Jdk8、Tomcat9安装包 根据Jenkins官网介绍,Jenkins支持Java8的版本如下: 我们选择2.164版本进行安装,根据版本号支持输入下载地址:https://archives.jenkins.io/war/2.164/jenkins.war,进行下载…

【牛客网题目】合并两个排序的链表

目录 描述 题目分析 描述 输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的。 数据范围:0≤n≤1000,1000≤节点值≤1000 要求:空间复杂度 O(1),时间复杂…

为什么我说 90% 的技术人搞副业都会失败?!

见字如面,我是军哥! 这几天有多位程序员读者请教我,如何搞副业?并且有一位已经搞了半年了,涨粉困难,这小伙子大概工作 2 年的样子,所在的公司算中等二线大厂吧。 我把和他们聊的内容总结了一下&…

vscode调教配置:快捷修复和格式化代码

配置vscode快捷键,让你像使用idea一样使用vscode,我们最常用的两个功能就是格式化代码和快捷修复,所以这里修改一下快捷修复和格式化代码的快捷键。 在设置中,找到快捷键配置: 然后搜索:快捷修复 在快捷键…

分库分表篇-1 分库分表介绍

文章目录 前言一、为什么要分库分表?二、分库分表的策略:2.1 垂直切分:2.2.1 垂直分库:2.2.2 垂直分表:2.2.3 垂直拆分的优缺点: 2.2 水平切分:2.2.1 库内分表:2.2.2 分库分表:2.2.3 水平切分优缺点: 三、分…

04-MySQL02

1、什么是索引下推? 索引下推(index condition pushdown )简称ICP,在Mysql5.6的版本上推出,用于优化查询。 需求: 查询users表中 "名字第一个字是张,年龄为10岁的所有记录"。 SELECT * FROM u…

无涯教程-JavaScript - FTEST函数

FTEST函数取代了Excel 2010中的F.TEST函数。 描述 该函数返回F检验的输出。 F检验返回两尾概率,即array1和array2的方差没有显着差异。使用此功能可以确定两个样本是否具有不同的方差。 语法 FTEST (array1, array2)争论 Argument描述Required/OptionalArray1The first ar…

【仿写spring之ioc篇】三、检查是否实现了Aware接口并且执行对应的方法

Aware接口 Aware接口中只是设置了对应的set方法,目前只定义了三个Aware 以BeanNameAware为例 package com.ez4sterben.spring.ioc.factory.aware;/*** bean名字清楚** author ez4sterben* date 2023/08/31*/ public interface BeanNameAware {/*** 设置beanName* …

老胡的周刊(第106期)

老胡的信息周刊[1],记录这周我看到的有价值的信息,主要针对计算机领域,内容主题极大程度被我个人喜好主导。这个项目核心目的在于记录让自己有印象的信息做一个留存以及共享。 🎯 项目 quivr[2] Quivr 是您在云中的第二个大脑&…

Mysql数据库事务隔离级别造成死锁

场景:如下代码,获取数据库连接,删除权限的时候,会造成数据库死锁. 代码 日志: 数据库: SHOW OPEN TABLES where In_use > 0; 问题分析:测试环境Centos7操作系统,Mysql5.7.40版本程序运行正常,开发环境Windows操…

设计模式行为型-模板模式

文章目录 一:模板方法设计模式概述1.1 简介1.2 定义和目的1.3 关键特点1.4 适用场景 二:模板方法设计模式基本原理2.1 抽象类2.1.1 定义和作用2.1.2 模板方法2.1.3 具体方法 2.2 具体类2.2.1 定义和作用2.2.2 实现抽象类中的抽象方法2.2.3 覆盖钩子方法 …

学生信息管理系统MIS(前端)

改造HTML文件 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>学生信息管理系统MIS</title><!-- link在HTML文件中,引入外部的css文件 rel的值是固定写法,stylesheet样式表href用来指定样式表的位置--><lin…

CleanMyMac X2024软件最新版本更新下载

CleanMyMac X是一款颇受欢迎的专业清理软件&#xff0c;拥有十多项强大的功能&#xff0c;可以进行系统清理、清空废纸篓、清除大旧型文件、程序卸载、除恶意软件、系统维护等等&#xff0c;并且这款清理软件操作简易&#xff0c;非常好上手&#xff0c;特别适用于那些刚入手苹…

企业架构LNMP学习笔记5

Nginx&#xff1a; 常见用法&#xff1a; 1&#xff09;web服务器软件 httpd http协议 同类的web服务器软件&#xff1a;apache Nginx&#xff08;俄罗斯&#xff09;IIS&#xff08;微软&#xff09;lighttpd&#xff08;德国&#xff09; 2&#xff09;代理服务器 反向代…

springboot:时间格式化的5种方法(解决后端传给前端的时间格式转换问题)推荐使用第4和第5种!

本文转载自&#xff1a;springboot&#xff1a;时间格式化的5种方法&#xff08;解决后端传给前端的时间显示不一致&#xff09;_为什么前端格式化日期了后端还要格式化_洛泞的博客-CSDN博客 时间问题演示 为了方便演示&#xff0c;我写了一个简单 Spring Boot 项目&#xff…

设计模式-工厂模式Factory

工厂模式 b.工厂方法模式 (Factory Method) (重点)1) 简单工厂 Simple Factory1.a) 简单工厂的好处 2) 工厂方法 Factory Method2.a) 对工厂进行抽象化 (版本一)2.b) 对工厂进行缓存 (版本二)2.c) 加载配置文件到缓存中 (版本三)c.1) 产品线 c.抽象工厂模式 (Abstract Factory)…

五子棋游戏禁手算法的改进

五子棋游戏禁手算法的改进 五子棋最新的禁手规则&#xff1a; 1&#xff0e;黑棋禁手判负、白棋无禁手。黑棋禁手有“三三”&#xff08;包括“四三三”&#xff09;、“四四”&#xff08;包括“四四三”&#xff09;和“长连”。黑棋只能以“四三”取胜。 2&#xff0e;黑方…

B端系统设计之【权限】详解

衡量B端产品系统好坏的一个重要标准就是它的权限是否细致&#xff0c;拓展性是否强。 权限管理是B端产品系统的基础&#xff0c;好的权限管理系统延展性较强&#xff0c;即使业务发生变化也能避免大改和推倒重建。 权限分类 1、功能权限 功能权限是指用户登录系统之后&#xff…