HiSDP —— 高效的C++软件开发平台

本文涉及的产品
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
云原生网关 MSE Higress,422元/月
性能测试 PTS,5000VUM额度
简介: 目前阿里集团每天有近1000PB的数据是通过LogAgent采集的,为了让LogAgent做到资源占用省和高效采集,背后是基于HiSDP去构建的。

目前阿里集团每天有近1000PB的数据是通过LogAgent采集的,为了让LogAgent做到资源占用节省和高效采集,背后是基于HiSDP去构建的。

缘由

当决定采用C++编程语言去开发一个软件时,紧接着所面临的问题是软件库、平台与框架的选择。当然,选择的范围估计很大程度来自开源软件。进一步地,无外乎两种思路:

  • 根据所开发软件的需要选择各种合适的开源软件,然后将这些开源软件组合到一起去完成软件开发工作。这种方式所带来的问题在于,将各个开源软件拼凑到一起需要耗费一定的精力。此外,可能因为踩各开源软件中的坑而导致最终软件产品的稳定期拉得更长,后期的维护成本也更高。
  • 采用市面上成熟的大型开源软件项目,对之进行裁剪去满足项目开发的需要。这一方式虽说在裁剪上需要消耗一定的精力(这是一次性的工作内容),但由于大型项目的成熟确保了其所选择的各个开源子项目的质量得到了充分的验证而避免我们再踩坑,且其中所使用各开源软件的代码能很好地起到示范作用去帮助工程师更快地上手写出更具质量的代码。HiSDP就是基于这一思路而产生的!

HiSDP源于Google的Chromium开源软件,即大家平时经常使用的Chrome浏览器的开源版。作者因为曾经有大约3年半的时间是基于Chromium做淘宝浏览器和UC浏览器电脑版的软件开发工作,所以对Chromium背后所蕴藏的Google之工程理念和对工程质量的要求有着深刻的认识与体感,

包含但不限于:

  • 重度依赖单元测试。Chromium对单元测试代码的组织与实践形成了一套行之有效、很容易上手的工程规范,很好地示范了如何通过gtest/gmock去编写单元测试代码,并让执行单元测试的动作与开发环境做到了无缝整合。
    特别重视程序的性能度量。Google一直力争让Chrome浏览器在运行速度上与竞品保持优势,为此非常重视性能数据的可视化,tracing功能就是在这样的背景下产生的(用Chrome浏览器导航到chrome://tracing这个网址就可以对浏览器打开的网页进行性能tracing)。
  • 极度关注程序的编译效率。由于Chromium的代码量很是庞大,所以这个项目从开始之初就在一直持续地优化整个工程的编译速度。除了gn+ninja这一编译工具组合,Chromium的代码组织与程序格式也为了加速编译而做了规范并细致地执行到位。
  • 将程序的可查错性当作良好的编程习惯。整个Chromium的代码随处可见DCHECK(与assert相似),以及在关键点存在CHECK(会产生dump文件而记录下发生问题的现场)。
  • 严格执行Google C++ Coding Style中所定义的编码规范。为了帮助新手更好地掌握这一规范,甚至还开发出了cpplint这样的代码规范扫描工具(用Python实现的)。
  • 对软件设计质量的持续极致追求。Chrome浏览器大约6周出一个大版本,每个版本都能看到对之前没有做到位的完善痕迹,有的改进尺度之大足以让人为之动容。这种工程实践所带来的结果是Chromium的整体代码质量很高且久经考验。

基于我对Chromium的这些认识,很自然地想到将那些能力与气质带到其他项目中,希望能“站在巨人的肩膀上”以“杀鸡用牛刀”的思路去开发其他C++软件。

HiSDP是High-productivity Software Development Platform的简写。取这个名的本意是希望他成为C++编程语言的高效软件开发平台。然而,将Chromium裁剪成HiSDP并使之适合用于集团服务器环境下的软件开发还是经历了一些波折。最大的问题在于,Chromium的开发环境基本上是基于Ubuntu 16.04构建的,存在内核版本比集团环境的更高而导致无法直接正常运行的问题,当然这个问题经过一番折腾后得到了解决。

能力

  • 具备跨Windows、Mac和Linux操作系统的软件开发能力。HiSDP完全保留了Chomium的base库,该库抽象并封装了file、string、threading、process、message_loop、memory、profiling等诸多内容,能很好地满足其他软件开发工作的基础需要。
  • 具备复杂工程的高效源代码组织与快速构建能力。通过gn文件(与CMakeLists.txt文件的作用相似)对源文件进行管理;通过ninja(与make类似)调用编译器完成编译工作;通过DEPS文件管理工程所依赖的第三方Git仓库。可以想象,gn文件的语法完全考虑了跨平台场景下源代码的组织形式。构建速度将随着项目规模的增大而表现得愈加明显。
  • 全面复用与Chromium配套的各种开发工具。Chromium将各种工具都放到了depot_tools 这个独立的Git仓库中,其中包含了支撑高效软件开发工作的各种脚手架工具。
  • 实现了被开发软件与HiSDP自身的很好解耦。通过引入HiApp的概念,将基于HiSDP开发的软件的源代码都放在一个独立的Git仓库中,将HiApp与这个仓库挂钩而实现了与HiSDP的代码组合。下面的命令示例了如何获取depot_tools、HiSDP和LogAgent的代码,希望有助于帮助理解HiApp的概念。
$ git clone http://gitlab.alibaba-inc.com/middleware-expert/depot_tools.git depot_tools
$ vim ~/.barshrc    // 追加下面内容
  export PATH="/path/to/depot_tools/:$PATH"
$ source ~/.barshrc
$ mkdir LogAgent && cd LogAgent
$ fetch hisdp --hiapp=git@gitlab.alibaba-inc.com:LogAgent/Agent.git@release-3.0

简单说来,使用depot_tools和HiSDP的开发体验与Chromium是完全一样的。

价值

  • 解决“技术可以,开发不行”现象。当个体对软件工程没有足够的认识,并不清楚除了编程语言和算法外,还有其他关键因素影响着开发效率和最终的软件质量,那时就会表现出“技术可以,开发不行”,即各种技术知识都知道,但却做不到有质效地开展软件开发工作。HiSDP因为继承了Chromium十多年所沉淀的工程经验,所以是一个很好的学习场所,即便一开始没有意识到那么做背后所蕴含的理念,只要模仿就可能最终贯通领悟。
  • 助力跨平台软件开发。由于天然地支持开发可运行于Windows、Mac和Linux上的软件,HiApp因为有这样的“底座”而更容易实现跨平台开发。
  • 提高软件开发效率。这一点是显而易见的,围绕工程各个方面的脚手架工作在HiSDP上都已具备,只需在HiApp的开发中专注于所需解决的业务问题。
  • 通过代码共享解决了版本依赖问题。与大多C++程序员所希望的所不同的是,HiSDP不是以库的形式呈现的,而是完全以源码形式。借助HiApp这一概念,使得被开发软件的源代码也成为了HiSDP的一部分。这一形式省去了采用库形式发布所带来的版本升级与同步问题,当HiSDP中修复了缺陷时,由HiApp的开发者通过pull最新的代码做到修复。如果读者细想这一点,会对其价值有更深的认识。

挑战

正如“天下没有免费的午餐”所表达的哲理,当我们在享受HiSDP所带来的优势时,也不得不面临一些挑战,即掌握HiSDP需要一定的时间、其入门的门坎相对要高出不少。诚然,这一挑战需要工程师个体通过学习去应对,且学习过程需要在即便上手后仍持续保持,因为HiSDP真的是一个巨大的知识宝藏,从技术和工程领域都给出了很多有启发性的实现参考和解决方案,非常值得“细品慢嚼”。

最后,LogAgent在刚过去的2018财年很好地用HiSDP演绎了“用牛刀杀鸡”的工程理念。

958ebaea1944957eb483cf0f9b6e7ea1.png

附录

相关文章
|
1月前
|
存储 算法 C++
【C++数据结构——查找】二分查找(头歌实践教学平台习题)【合集】
二分查找的基本思想是:每次比较中间元素与目标元素的大小,如果中间元素等于目标元素,则查找成功;顺序表是线性表的一种存储方式,它用一组地址连续的存储单元依次存储线性表中的数据元素,使得逻辑上相邻的元素在物理存储位置上也相邻。第1次比较:查找范围R[0...10],比较元素R[5]:25。第1次比较:查找范围R[0...10],比较元素R[5]:25。第2次比较:查找范围R[0..4],比较元素R[2]:10。第3次比较:查找范围R[3...4],比较元素R[3]:15。,其中是顺序表中元素的个数。
137 68
【C++数据结构——查找】二分查找(头歌实践教学平台习题)【合集】
|
1月前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
142 77
|
1月前
|
存储 C++
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
59 14
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
|
1月前
|
存储 C++ 索引
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
43 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
|
1月前
|
算法 C++
【C++数据结构——查找】二叉排序树(头歌实践教学平台习题)【合集】
【数据结构——查找】二叉排序树(头歌实践教学平台习题)【合集】 目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果: 任务描述 本关任务:实现二叉排序树的基本算法。 相关知识 为了完成本关任务,你需要掌握:二叉树的创建、查找和删除算法。具体如下: (1)由关键字序列(4,9,0,1,8,6,3,5,2,7)创建一棵二叉排序树bt并以括号表示法输出。 (2)判断bt是否为一棵二叉排序树。 (3)采用递归方法查找关键字为6的结点,并输出其查找路径。 (4)分别删除bt中关键
53 11
【C++数据结构——查找】二叉排序树(头歌实践教学平台习题)【合集】
|
1月前
|
C++ 芯片
【C++面向对象——类与对象】Computer类(头歌实践教学平台习题)【合集】
声明一个简单的Computer类,含有数据成员芯片(cpu)、内存(ram)、光驱(cdrom)等等,以及两个公有成员函数run、stop。只能在类的内部访问。这是一种数据隐藏的机制,用于保护类的数据不被外部随意修改。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。成员可以在派生类(继承该类的子类)中访问。成员,在类的外部不能直接访问。可以在类的外部直接访问。为了完成本关任务,你需要掌握。
68 19
|
1月前
|
存储 编译器 数据安全/隐私保护
【C++面向对象——类与对象】CPU类(头歌实践教学平台习题)【合集】
声明一个CPU类,包含等级(rank)、频率(frequency)、电压(voltage)等属性,以及两个公有成员函数run、stop。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。​ 相关知识 类的声明和使用。 类的声明和对象的声明。 构造函数和析构函数的执行。 一、类的声明和使用 1.类的声明基础 在C++中,类是创建对象的蓝图。类的声明定义了类的成员,包括数据成员(变量)和成员函数(方法)。一个简单的类声明示例如下: classMyClass{ public: int
50 13
|
1月前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
48 12
|
1月前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
46 10
|
1月前
|
算法 C++
【C++数据结构——图】最小生成树(头歌实践教学平台习题) 【合集】
【数据结构——图】最小生成树(头歌实践教学平台习题)目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:【合集】任务描述 本关任务:编写一个程序求图的最小生成树。相关知识 为了完成本关任务,你需要掌握:1.建立邻接矩阵,2.Prim算法。建立邻接矩阵 上述带权无向图对应的二维数组,根据它建立邻接矩阵,如图1建立下列邻接矩阵。注意:INF表示无穷大,表示整数:32767 intA[MAXV][MAXV];Prim算法 普里姆(Prim)算法是一种构造性算法,从候选边中挑
43 10