这是LevelDB 代码阅读系列博客的第一篇,更多内容见
主要内容
由于研究生工作需要用到LevelDB相关的知识,所以拜读一下谷歌大牛所写的LevelDB。对LevelDB和LSM Tree的介绍这里不进行介绍,后期有时间回来填坑。
想阅读源码,首先要先把代码编译通过并运行起来,这样我们才能在后期愉快的调试代码。本篇文章主要说明如何跑起LevelDB。
本系列文档基于LevelDB的1.22版本。
本篇主要分为三个部分:
- 编译并运行LevelDB
- LevelDB的Benchmark
- LevelDB模块的单元测试
编译并运行LevelDB
首先我们先去Github上把代码Clone下来。地址在这。
levelDB使用cmake构建。在工程README中已经给出了编译方法。
1 | mkdir -p build && cd build |
这采用了cmake外部编译的方法,好处就是编译生成的文件都在一个文件夹中,不会影响代码部分。
和内存数据库Redis不同。Redis编译完会有两个可执行文件,即CLient和Server。Server相当与一个一直运行在系统内的应用。而Client则是去连接它。而LevelDB编译完则是生成一个静态链接库。即build文件夹中的libleveldb.a文件。其类似用txt文件维护数据库而不是发送请求给server。
那我们要如何使用这个库呢?首先写一个简单的cpp程序。
1 |
|
这个程序非常简单,就是创建并打开数据库,插入一条KV对。我们可以看到我们include了一个用户程序 db.h。这个程序来源于levelDB中的include文件夹中。为了让其可用,我们要在cmake中加上其路径。
1 | include_directories(../leveldb-master/include) |
同时我们需要添加leveldb静态库和链接
1 | link_directories ("../leveldb-master/build/") |
cmake文件如下:
1 | cmake_minimum_required(VERSION 3.09) |
只需要 mkdir build && cd build && cmake .. && make. 就可以跑起了。会打印出KV对。
levelDB的benchmark
LevelDB自带了三种benchmark程序,即levelDB下benchmark目录中的三个文件。这里主要分析db_bench这个测试。(由于这个测试不需要其他依赖,而db_bench_sqlite3和db_bench_tree_db都需要额外的依赖。)
这个测试主要测试了顺序写(with/without async)。覆盖写,随机写(with/without sync)。顺序/随机删,顺序/逆序/随机读。在编译完成后就会在build目录下生成db_bench可执行文件。直接跑就可以,结果如下图。

可以看到,在关闭sync时,顺序写和随机写的性能差距(4 vs 9)相比于顺序读和随机读(0.1 vs 2-5)来说小了很多。这就可以看到LSM Tree的优秀写性能。同时看到,开启sync时,由于产生了很多小I/O,导致性能的大量损失(10000X)。以及compaction时的性能损失。
不过我感受最深刻的仍然是那个函数指针的使用。反正给我是完全想不到。
LevelDB的单元测试
LevelDB是Google两位大牛写的项目,自然使用了Google的测试框架。对谷歌测试框架相关内容我后期会单开坑来写,这里不进行表述。
在leveldb中的测试框架的使用很简单。只需要创建一个测试类,然后调用TEST macro(参数为测试类和测试名称)。框架也提供了一系列宏。这部分要等后期做修改的时候再进行验证。只需要再cmake文件中加入 leveldb_test就可以添加相应测试了。