目录
MatrixOne数据库是什么?
MatrixOne是一个新一代超融合异构数据库,致力于打造单一架构处理TP、AP、流计算等多种负载的极简大数据引擎。MatrixOne由Go语言所开发,并已于2021年10月开源,目前已经release到0.3版本。在MatrixOne已发布的性能报告中,与业界领先的OLAP数据库Clickhouse相比也不落下风。作为一款Go语言实现的数据库,可以达到C++实现的数据库一样的性能,其中一个很重要的优化就是利用Go语言自带的汇编能力,来通过调用SIMD指令进行硬件加速。本文就将对Go汇编及在MatrixOne的应用做详细介绍。
Github地址:https://github.com/matrixorigin/matrixone 有兴趣的读者欢迎star和fork。
Go汇编介绍
Go是一种较新的高级语言,提供诸如协程、快速编译等激动人心的特性。但是在数据库引擎中,使用纯粹的Go语言会有力所未逮的时候。例如,向量化是数据库计算引擎常用的加速手段,而Go语言无法通过调用SIMD指令来使向量化代码的性能最大化。又例如,在安全相关代码中,Go语言无法调用CPU提供的密码学相关指令。在C/C++/Rust的世界中,解决这类问题可通过调用CPU架构相关的intrinsics函数。而Go语言提供的解决方案是Go汇编。本文将介绍Go汇编的语法特点,并通过几个具体场景展示其使用方法。
本文假定读者已经对计算机体系架构和汇编语言有基本的了解,因此常用的名词(比如“寄存器”)不做解释。如缺乏相关预备知识,可以寻求网络资源进行学习,例如这里。
如无特殊说明,本文所指的汇编语言皆针对x86(amd64)架构。关于x86指令集,Intel和AMD官方都提供了完整的指令集参考文档。想快速查阅,也可以使用这个列表。Intel的intrinsics文档也可以作为一个参考。
为什么使用Go汇编?
维基百科把使用汇编语言的理由概括成3类:
- 直接操作硬件
- 使用特殊的CPU指令
- 解决性能问题
Go程序员使用汇编的理由,也不外乎这3类。如果你面对的问题在这3个类别里面,并且没有现成的库可用,就可以考虑使用Go汇编。
为什么不用CGO?
- 巨大的函数调用开销
- 内存管理问题
- 打破goroutine语义 若协程里运行CGO函数,会占据单独线程,无法被Go运行时正常调度。
- 可移植性差 交叉编译需要目的平台的全套工具链。在不同平台部署需要安装更多依赖库。
倘若在你的场景中以上几点无法接受,不妨尝试一下Go汇编。
Go汇编语法特点
根据Rob Pike的The Design of the Go Assembler,Go使用的汇编语言并不严格与CPU指令一一对应,而是一种被称作Plan 9 assembly的“伪汇编”。
The most important thing to know about Go’s assembler is that it is not a direct representation of the underlying machine. Some of the details map precisely to the machine, but some do not. This is because the compiler suite needs no assembler pass in the usual pipeline. Instead, the compiler operates on a kind of semi-abstract instruction set, and instruction selection occurs partly after code generation. The assembler works on the semi-abstract form, so when you see an instruction like MOV what the toolchain actually generates for that operation might not be a move instruction at all, perhaps a clear or load. Or it might correspond exactly to the machine instruction with that name. In general, machine-specific operations tend to appear as themselves, while more general concepts like memory move and subroutine call and return are more abstract. The details vary with architecture, and we apologize for the imprecision; the situation is not well-defined.
我们不用关心Plan 9 assembly与机器指令的对应关系,只需要了解Plan 9 assembly的语法特点。网络上有一些可获得的文档,如这里和这里。
一例胜千言,下面我们以最简单的64位整数加法为例,从不同方面来看Go汇编语法的特点。
// add.go
func Add(x, y int64) int64</