作者简介:夏克 ,从事金融行业核心系统设计开发工作多年,目前就职于某交易所子公司,现阶段负责国产数据库调研。已获得 OBCA、PCTA 等证书。
引子
由于时间和精力的原因,上一篇关于OceanBase二次开发的帖子Hello OceanBase!开启OB二次开发之后就很少在社区活动了。当然,还是要感谢社区小编和运营们不失时机的提醒与督促_。这两天在社区里面爬楼梯,翻了翻OB的相关帖子。近期OB社区的主旋律应该是性能相关主题——测试体验和性能调优等方面的。这个主题很好,很复杂,同时涉及的范围也很广,影响性能的因素也很多。我认为,如果把DB比作一辆车,那么车子能跑多快一般取决于三个方面:
- 车子的硬件条件,比如发动机的排量
- 车子本身的一些设计,比如变速箱的设计,涡轮增压,空气动力学的利用等一些工业设计
- 驾驶员本身的驾驶技能与技巧,以及对车子特点的熟悉程度
硬件条件对应数据库运行的基础设施(服务器,操作系统):目前主流的 Intel X86,主频可以达到(3.7GHz~4.1GHz)。但是这东西毕竟是进口的发动机不能自主可控,那么对应国产的发动机有海光 x86(2.0GHz~2.4GHz),鲲鹏 ARM(2.6GHz)等,虽然排量低一点,但是有更多的气缸,比如主流的 Kunpeng 920 2座*64=128核。在不同的场景下不同的发动机各有优势,这里不做对比。
车子本身的设计对应的就是数据库的设计与架构:包括各种优化器,算子下推,顺序写等等。
驾驶员就是指 DBA 和数据库使用者:这些直接的数据库用户对数据库的掌握和了解情况,一定程度上也会影响车子的速度。车子到手后是否能发挥最佳的性能,对于 DBA 这些老司机来说任重而道远。
本文将针对第一点进行探索,先换个底盘(openEuler)和发动机(Kunpeng)看看效果,而第二点是数据库大厂工程师们努力的目标,至于第三点就交给“老司机”吧~
概要
2022-03-30,OceanBase 社区 release 了3.1.3_CE 版本。值得注意的是“新增支持 ARM 平台”功能。我相信这一版本的发布是社区版 OceanBase 的一个重要里程碑,在信创的大背景下,ARM 已成为主要的替代方案。严重点讲,缺失了对 ARM 的支持,可能会损失一半的市场。如前所述,如果把 DB 比作汽车,除了性能指标外,市场保有量才是决定是否可以长期稳定立足行业的关键,有了保有量就会有更多的用户反馈,用户反馈又决定了产品的质量,质量提高又会带动销量和保有量,这是一个良性循环的过程,也是目前各大国产数据库厂商努力推广,占领市场的原因吧。
目前 ARM 版支持的编译操作系统只有(alios和centos)两种,但主流的可适配 ARM 架构的操作系统还有很多,目前的国产操作系统中大部分是基于华为欧拉和阿里龙蜥两大开源社区的商业发行版,知名的包括麒麟 Kylin v10,统信 UOS(1021a:基于阿里龙蜥内核,1021e:基于华为 openEuler 内核)。如果使用 ARM 架构,大部分用户会选择基于 openEuler 内核的操作系统(针对鲲鹏有优化)。因此,虽然 OceanBase 已经 release 了 ARM 版本(实测,可以直接运行在鲲鹏+欧拉上),但针对性的优化应该还不够完善,当然这只是时间问题,我相信很快就会有 ARM 的优化方案和版本推出。
本文将针对 ARM 版 OceanBase 迁移到 Kunpeng+openEuler 进行尝试与实践。目标是,通过源码重新编译3.1.3_CE for ARM,使用华为的毕昇编译器(HUAWEI BiSheng Compiler 2.1.0.B010 clang version 12.0.0 (clang-0749c5924208 flang-d6f2a3bc24a)替代原有的 llvm 11.0.1。使用 jemalloc 替代原有的内存分配器,最终达到性能提升的目的。
写在前面
可能这又是一篇小众的帖子,社区里面的“老司机”们未必能看完。所以先把成果放在这里吧。
- 支持在鲲鹏+欧拉上可编译的源码仓库(fork 于社区版源码仓库):https://github.com/Frank-gh/oceanbase
注意:切换至 openEuler 分支
2.使用方式
git clone https://github.com/Frank-gh/oceanbase.git cd oceanbase git checkout openEuler sh build release --init --make
3.该仓库将持续维护,期待各位的测试结果和问题反馈。
总体目标
- OceanBase 源码可以在,鲲鹏 920 + openEuler 系统上编译;
- 替换通用的 LLVM,CLANG,使用针对 Kunpeng 优化的毕昇编译器(基于 clangv12.0.0);——后续会针对编译器升级进行性能测试
- 增加鲲鹏优化的编译选项,并使用 jemalloc 替换自带的内存分配器;——后续会针对调整进行新能测试对比
- 最终希望能得到一个在鲲鹏+欧拉上的定制优化版本,并提供给社区用户进行测试体验。
一、环境准备
使用华为的 ECS,本次实践只为了编译,所以配置要求不高,但编译比较吃 CPU 和内存,太小的话会出现 OOM 的情况,建议比以下配置使用更多的CPU和内存(推荐:16c,32G)
操作系统信息
[root@ecs-613f ~]# cat /etc/os-release NAME="openEuler" VERSION="20.03 (LTS)" VERSION_ID="20.03" PRETTY_NAME="openEuler 20.03 (LTS)" ANSI_COLOR="0;31"
二、编译准备
2.1 获取源码
git clone https://github.com/Frank-gh/oceanbase.git
cd oceanbase
## 切换到 3.1.3_CE tag
git checkout 3.1.3_CE
## 创建新的分支
git checkout -b openEuler
2.2 安装依赖
理想情况下,OceanBase 所有的依赖会在编译前都自动下载 deps/3rd/pkg 目录并安装到 deps/3rd/usr/local/oceanbase/deps和deps/3rd/usr/local/oceanbase/devtools 下面,但实际操作,虽然在 devtools 下已安装,但是编译的时候并未 cover 全部。因此需要安装如下包,主要是语法解析和词法解析(lex,yacc)的包。
yum install flex bison bison-devel
另外一个可以选择安装,如果不安装可以设置环境变量来解决:
export LD_LIBRARY_PATH=$SCR_DIR/deps/3rd/usr/local/oceanbase/devtools/lib64:$LD_LIBRARY_PATH
或者直接安装
yum install libatomic
三、调试编译脚本
3.1 首次编译
[root@ecs-613f oceanbase]# ./build.sh release --init --make
[ERROR] 'openEuler 20.03 (LTS) (aarch64)' is not supported yet.
调试: 使用 -x 调试 build.sh 脚本 sh -x build.sh release --init --make
+ do_init + cd /root/oceanbase/deps/3rd + bash dep_create.sh [ERROR] 'openEuler 20.03 (LTS) (aarch64)' is not supported yet. + exit 1
发现在执行 dep_create.sh 脚本时报错,继续跟踪…
调试: 使用 -x 调试 dep_create.sh 脚本 bash -x dep_create.sh
[root@ecs-613f 3rd]# cd /root/oceanbase/deps/3rd [root@ecs-613f 3rd]# bash -x dep_create.sh + get_os_release + aarch64x == x86_64x + aarch64x == aarch64x + case "$ID" in + not_supported + echo '[ERROR] '\''openEuler 20.03 (LTS) (aarch64)'\'' is not supported yet.' [ERROR] 'openEuler 20.03 (LTS) (aarch64)' is not supported yet. + return 1 + exit 1
is not supported yet ,好吧,开始撸脚本。
可以看到下面的脚本中支持 aach64上编译的操作系统目前只有 alios 和 centos。
脚本中获取操作系统版本信息的逻辑
[root@ecs-613f ~]# source /etc/os-release [root@ecs-613f ~]# PNAME=${PRETTY_NAME:-"${NAME} ${VERSION}"} [root@ecs-613f ~]# echo $PNAME openEuler 20.03 (LTS) [root@ecs-613f ~]# OS_ARCH="$(uname -m)" [root@ecs-613f ~]# PNAME="${PNAME} (${OS_ARCH})" [root@ecs-613f ~]# echo $PNAME openEuler 20.03 (LTS) (aarch64)
修改脚本,增加 openEuler 的分支,同时,依赖包列表会在同级目录下找到 oceanbase.el8.aarch64.deps ,当然也可以新建一个 Euler的deps,这里就不做了,后续再完善。
oceanbase.el8.aarch64.deps 内容如下:(dep_create.sh通过配置中的 repo下载对应的 rpm 包,并安装的指定目录)
os=8 arch=aarch64 repo=http://mirrors.aliyun.com/oceanbase/development-kit/el/8/aarch64/ [deps] devdeps-gtest-1.8.0-16.el8.aarch64.rpm devdeps-isa-l-static-2.22.0-17.el8.aarch64.rpm devdeps-libcurl-static-7.29.0-16.el8.aarch64.rpm devdeps-libunwind-static-1.6.2-12.el8.aarch64.rpm devdeps-mariadb-connector-c-3.1.12-16.el8.aarch64.rpm devdeps-openssl-static-1.0.1e-12.el8.aarch64.rpm devdeps-libaio-0.3.112-6.el8.aarch64.rpm devdeps-rapidjson-1.1.0-3.el8.aarch64.rpm [tools] obdevtools-binutils-2.30-7.el8.aarch64.rpm obdevtools-bison-2.4.1-9.el8.aarch64.rpm obdevtools-ccache-3.7.12-6.el8.aarch64.rpm obdevtools-cmake-3.20.2-15.el8.aarch64.rpm obdevtools-flex-2.5.35-10.el8.aarch64.rpm obdevtools-gcc-5.2.0-15.el8.aarch64.rpm obdevtools-llvm-11.0.1-40.el8.aarch64.rpm [tools-deps] devdeps-rocksdb-6.22.1-26.el8.aarch64.rpm
至此,基本的修改已经完成,可以再编译试试。
3.2 再次编译
回到源码根目录,重新编译。
[root@ecs-613f oceanbase]# ./build.sh release --init --make
如果顺利,再次编译会直接成功,成功后查看生成的 observer。
[root@ecs-613f observer]# file observer observer: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, BuildID[md5/uuid]=b936eff9babeed59708f2e5ccdd12518, with debug_info, not stripped [root@ecs-613f observer]# ldd observer linux-vdso.so.1 (0x0000fffd9e060000) libm.so.6 => /lib64/libm.so.6 (0x0000fffd9df80000) libpthread.so.0 => /lib64/libpthread.so.0 (0x0000fffd9df40000) libdl.so.2 => /lib64/libdl.so.2 (0x0000fffd9df10000) librt.so.1 => /lib64/librt.so.1 (0x0000fffd9dee0000) libatomic.so.1 => /root/oceanbase/deps/3rd/usr/local/oceanbase/devtools/lib64/libatomic.so.1 (0x0000fffd9deb0000) libc.so.6 => /lib64/libc.so.6 (0x0000fffd9dd20000) /lib/ld-linux-aarch64.so.1 (0x0000fffd9e070000)
查看 pkg 目录,可以看到已经下载的 rpm 包:
[root@ecs-613f 3rd]# tree pkg/ pkg/ ├── devdeps-gtest-1.8.0-16.el8.aarch64.rpm ├── devdeps-isa-l-static-2.22.0-17.el8.aarch64.rpm ├── devdeps-libaio-0.3.112-6.el8.aarch64.rpm ├── devdeps-libcurl-static-7.29.0-16.el8.aarch64.rpm ├── devdeps-libunwind-static-1.6.2-12.el8.aarch64.rpm ├── devdeps-mariadb-connector-c-3.1.12-16.el8.aarch64.rpm ├── devdeps-openssl-static-1.0.1e-12.el8.aarch64.rpm ├── devdeps-rapidjson-1.1.0-3.el8.aarch64.rpm ├── devdeps-rocksdb-6.22.1-26.el8.aarch64.rpm ├── obdevtools-binutils-2.30-7.el8.aarch64.rpm ├── obdevtools-bison-2.4.1-9.el8.aarch64.rpm ├── obdevtools-ccache-3.7.12-6.el8.aarch64.rpm ├── obdevtools-cmake-3.20.2-15.el8.aarch64.rpm ├── obdevtools-flex-2.5.35-10.el8.aarch64.rpm ├── obdevtools-gcc-5.2.0-15.el8.aarch64.rpm └── obdevtools-llvm-11.0.1-40.el8.aarch64.rpm
其中 obdevtools-llvm-11.0.1-40.el8.aarch64.rpm和obdevtools-gcc-5.2.0-15.el8.aarch64.rpm 这两个包实际上是可以考虑进行升级。对应 Kunpeng 上的定制编译器,分别是 BiSheng Compiler 2.1.0(基于 clang v12) 和 GCC for openEuler(基于gcc v9.3.0),这两款针对 Kunpeng ARM 架构都有不同程度的优化,也是本次实践想要得到的结果——即通过编译选项,内存分配器,操作系统参数的优化,是否可以提升 OceanBase 在鲲鹏 ARM上的性能。
3.3 编译器升级
下载毕昇编译器
wget -c https://mirrors.huaweicloud.com/kunpeng/archive/compiler/bisheng_compiler/bisheng-compiler-2.1.0-aarch64-linux.tar.gz
将 tar 包放在 deps/3rd 目录下。
修改 dep_create.sh 脚本
增加以下几行代码——下载,安装毕昇编译器。
修改依赖包列表 oceanbase.el8.aarch64.deps
删掉 obdevtools-llvm-11.0.1-40.el8.aarch64.rpm 这行。
3.4 再来一次
回到源码根目录,重新编译。
[root@ecs-613f oceanbase]# ./build.sh release --init --make
解决编译报错
第三次编译会报错,原因为新的编译器不支持宏嵌套的使用语法。
In file included from /root/oceanbase/build_release/deps/oblib/src/rpc/CMakeFiles/oblib_rpc.dir/Unity/unity_oblib_rpc_common/1_cxx.cxx:51: /root/oceanbase/deps/oblib/src/rpc/obrpc/ob_rpc_processor_base.cpp:454:14: error: '(' and '{' tokens introducing statement expression appear in different macro expansion contexts [-Werror,-Wcompound-token-split-by-macro] } else if (FALSE_IT({ NG_TRACE(transmit); })) { ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /root/oceanbase/deps/oblib/src/lib/utility/utility.h:29:5: note: expanded from macro 'FALSE_IT' (stmt); \ ^ /root/oceanbase/deps/oblib/src/rpc/obrpc/ob_rpc_processor_base.cpp:454:23: note: '{' token is here } else if (FALSE_IT({ NG_TRACE(transmit); })) { ^ /root/oceanbase/deps/oblib/src/lib/utility/utility.h:29:6: note: expanded from macro 'FALSE_IT' (stmt); \ ^~~~ In file included from /root/oceanbase/build_release/deps/oblib/src/rpc/CMakeFiles/oblib_rpc.dir/Unity/unity_oblib_rpc_common/1_cxx.cxx:51: /root/oceanbase/deps/oblib/src/rpc/obrpc/ob_rpc_processor_base.cpp:454:45: error: '}' and ')' tokens terminating statement expression appear in different macro expansion contexts [-Werror,-Wcompound-token-split-by-macro] } else if (FALSE_IT({ NG_TRACE(transmit); })) { ^ /root/oceanbase/deps/oblib/src/lib/utility/utility.h:29:6: note: expanded from macro 'FALSE_IT' (stmt); \ ^~~~ /root/oceanbase/deps/oblib/src/rpc/obrpc/ob_rpc_processor_base.cpp:454:14: note: ')' token is here } else if (FALSE_IT({ NG_TRACE(transmit); })) { ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /root/oceanbase/deps/oblib/src/lib/utility/utility.h:29:10: note: expanded from macro 'FALSE_IT' (stmt); \ ^ [ 44%] Building CXX object deps/oblib/src/lib/compress/CMakeFiles/oblib_compress.dir/ob_stream_compressor.cpp.o 2 errors generated. make[2]: *** [deps/oblib/src/rpc/CMakeFiles/oblib_rpc.dir/build.make:94: deps/oblib/src/rpc/CMakeFiles/oblib_rpc.dir/Unity/unity_oblib_rpc_common/1_cxx.cxx.o] Error 1 make[1]: *** [CMakeFiles/Makefile2:4083: deps/oblib/src/rpc/CMakeFiles/oblib_rpc.dir/all] Error 2
解决方案,修改源代码 deps/oblib/src/rpc/obrpc/ob_rpc_processor_base.cpp
去掉语法糖的写法 FALSE_IT ,修改后代码风格有点丑,逻辑应该没有问题,后续有时间回归一下单元测试,验证逻辑是否正确。
3.5 再再次编译
回到源码根目录,重新编译。
[root@ecs-613f oceanbase]# ./build.sh release --init --make
查看 clang 版本
[root@ecs-613f devtools]# /root/oceanbase/deps/3rd/usr/local/oceanbase/devtools/bin/clang -v HUAWEI BiSheng Compiler 2.1.0.B010 clang version 12.0.0 (clang-0749c5924208 flang-d6f2a3bc24a5) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /root/oceanbase/deps/3rd/usr/local/oceanbase/devtools/bin Found candidate GCC installation: /root/oceanbase/deps/3rd/usr/local/oceanbase/devtools/bin/../lib/gcc/aarch64-redhat-linux/5.2.0 Found candidate GCC installation: /usr/lib/gcc/aarch64-linux-gnu/7.3.0 Selected GCC installation: /usr/lib/gcc/aarch64-linux-gnu/7.3.0 Candidate multilib: .;@m64 Selected multilib: .;@m64
编译通过~
四、升级内存分配器
修改 cmake/ENV.cmake
-mtune=tsv110 :aarch 流水线优化选项
-ljemalloc:内存分配器
最后一次编译
回到源码根目录,重新编译。
[root@ecs-613f oceanbase]# ./build.sh release --init --make
编译成功~
五、验证
5.1 链接情况验证
ldd 可以看到 libjemalloc 可以成功链接。
5.2 查看 observer 编译版本信息
可以看到 BUILD_VRANCH: openEuler
六、FQA
Q1:基础编译 OceanBase 报错
CMake Error at src/sql/parser/CMakeLists.txt:65 (add_library): Cannot find source file: sql_parser_mysql_mode_lex.c CMake Error at src/sql/parser/CMakeLists.txt:65 (add_library): No SOURCES given to target: ob_sql_proxy_parser_objects CMake Error at src/sql/parser/CMakeLists.txt:93 (add_library): No SOURCES given to target: ob_sql_server_parser_static CMake Error at src/sql/parser/CMakeLists.txt:72 (add_library): No SOURCES given to target: ob_sql_server_parser_objects CMake Error at src/sql/parser/CMakeLists.txt:88 (add_library): No SOURCES given to target: ob_sql_proxy_parser_static
A1:缺少语法、词法分析的依赖 flex,bison
yum install flex bison bison-devel
Q2:更换 clang 版本后编译报错
In file included from /root/oceanbase/build_release/deps/oblib/src/rpc/CMakeFiles/oblib_rpc.dir/Unity/unity_oblib_rpc_common/1_cxx.cxx:51: /root/oceanbase/deps/oblib/src/rpc/obrpc/ob_rpc_processor_base.cpp:454:14: error: '(' and '{' tokens introducing statement expression appear in different macro expansion contexts [-Werror,-Wcompound-token-split-by-macro] } else if (FALSE_IT({ NG_TRACE(transmit); })) { ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /root/oceanbase/deps/oblib/src/lib/utility/utility.h:29:5: note: expanded from macro 'FALSE_IT' (stmt); \ ^ /root/oceanbase/deps/oblib/src/rpc/obrpc/ob_rpc_processor_base.cpp:454:23: note: '{' token is here } else if (FALSE_IT({ NG_TRACE(transmit); })) { ^ /root/oceanbase/deps/oblib/src/lib/utility/utility.h:29:6: note: expanded from macro 'FALSE_IT' (stmt); \ ^~~~ In file included from /root/oceanbase/build_release/deps/oblib/src/rpc/CMakeFiles/oblib_rpc.dir/Unity/unity_oblib_rpc_common/1_cxx.cxx:51: /root/oceanbase/deps/oblib/src/rpc/obrpc/ob_rpc_processor_base.cpp:454:45: error: '}' and ')' tokens terminating statement expression appear in different macro expansion contexts [-Werror,-Wcompound-token-split-by-macro] } else if (FALSE_IT({ NG_TRACE(transmit); })) { ^ /root/oceanbase/deps/oblib/src/lib/utility/utility.h:29:6: note: expanded from macro 'FALSE_IT' (stmt); \ ^~~~ /root/oceanbase/deps/oblib/src/rpc/obrpc/ob_rpc_processor_base.cpp:454:14: note: ')' token is here } else if (FALSE_IT({ NG_TRACE(transmit); })) { ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /root/oceanbase/deps/oblib/src/lib/utility/utility.h:29:10: note: expanded from macro 'FALSE_IT' (stmt); \ ^ [ 44%] Building CXX object deps/oblib/src/lib/compress/CMakeFiles/oblib_compress.dir/ob_stream_compressor.cpp.o 2 errors generated. make[2]: *** [deps/oblib/src/rpc/CMakeFiles/oblib_rpc.dir/build.make:94: deps/oblib/src/rpc/CMakeFiles/oblib_rpc.dir/Unity/unity_oblib_rpc_common/1_cxx.cxx.o] Error 1 make[1]: *** [CMakeFiles/Makefile2:4083: deps/oblib/src/rpc/CMakeFiles/oblib_rpc.dir/all] Error 2
A2:修改代码逻辑避免宏嵌套
七、总结
至此,整个迁移工作已经完成,使用时可以通过手工替换完成升级,后续会提供 rpm 的形式发布。文章逻辑是按照实操过程进行的记录,反复编译了5次,如果大家想节省时间的话可以看完整个操作流程,统一修改后,一次编译完成。当然,最简单的方法是直接去 git 仓库 clone 源码后切换分支进行编译。欢迎各位小伙伴和老司机们进行测试,该仓库会一直维护到官方有类似分支或版本后删除,期待各位的测试结果和问题反馈。
八、写在后面
海纳百川、有容乃大。信创的大背景下,国产硬件、操作系统、数据库、中间件等基础软件行业迎来了春天,这既是机遇又是挑战。头部的大厂既是水平领域的竞争对手,又是垂直领域的合作伙伴。而作为这个行业的从业者,我们既要看到在基础软件领域的差距,又要砥砺前行,自强不息。
有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。 与各位共勉。
感谢所有在信创领域一起奋斗的小伙伴们,让我们一起见证国产数据库百花齐放的春天,艳阳高照的夏天,硕果累累的秋天。
最后的最后,您有任何疑问都可以通过以下方式联系到我们~
联系我们
欢迎广大 OceanBase 爱好者、用户和客户随时与我们联系、反馈,方式如下:
社区版官网论坛
社区版项目网站提 Issue
钉钉群:33254054