代码说明:
HWDB
添加YCSB测试的代码样例:https://github.com/zzh-wisdom/YCSB-HWDB第二个是一位大佬根据第一个翻译过来的C++版本的代码。然后第三个代码都是实验室学长实现的,我只是在学习学习~,这里附上学长的代码链接:
https://github.com/a993096281/YCSB-HWDB
代码中还包含对RocksDB
的YCSB测试的实现,还是很有参考意义的。
代码框架简要说明:
下面是为自己实现的数据库添加YCSB测试的过程,以及部分代码的解释。
db.h
中的接口函数在文件core/db.h
文件中定义了一个抽象类DB
。
namespace ycsbc {
class DB {
public:
typedef std::pair<std::string, std::string> KVPair;
static const int kOK = 0;
static const int kErrorNoData = 1;
static const int kErrorConflict = 2;
virtual void Init() { }
virtual void Close() { }
virtual int Read(const std::string &table, const std::string &key,
const std::vector<std::string> *fields,
std::vector<KVPair> &result) = 0;
virtual int Scan(const std::string &table, const std::string &key, const std::string &max_key,
int record_count, const std::vector<std::string> *fields,
std::vector<std::vector<KVPair>> &result) = 0;
virtual int Update(const std::string &table, const std::string &key,
std::vector<KVPair> &values) = 0;
virtual int Insert(const std::string &table, const std::string &key,
std::vector<KVPair> &values) = 0;
virtual int Delete(const std::string &table, const std::string &key) = 0;
virtual bool HaveBalancedDistribution() { return true; };
virtual void PrintStats() {};
virtual ~DB() { }
};
} // ycsbc
中间的五个函数为未实现的虚函数。
为自己的数据库定一个类,并继承抽象类DB
时,必须要实现这五个虚函数。另外几个已经实现的虚函数也可以根据需要进行重写。
文件db/basic_db.h
中给出了一个最简单的实现样例,可以参考。
在为自己的数据库实现接口时,推荐使用链接库的方式,这样可以将自己数据库的代码与YSCB测试的代码分离。编译时,通过链接库的方式将自己数据库的代码与YCSB编译到一起。
/usr/local/lib/
路径下。/usr/local/include/
路径下使用时包含相应的头文件即可。
注意的是,编译时需要加上链接库参数,如-lrocksdb
。
文件db/db_factory.cc
文件中,只实现了一个方法CreateDB
。
该函数的功能是根据传入的参数创建对应数据库的类(前一节实现的),然后返回值为它的父类DB
。
这个函数可以看成是YCSB代码与自己实现的数据库代码之间连接的桥梁。
ycsbc.cc
该文件是测试主逻辑实现的地方,可以直接复用已有的代码,不做任何修改。这里主要说一下该文件实现的逻辑。
首先使用ParseCommandLine
函数解释从命令行中传入的参数,参数存放到类utils::Properties
中。
int main( const int argc, const char *argv[]) {
utils::Properties props;
Init(props);
string file_name = ParseCommandLine(argc, argv, props);
...
}
命令行参数主要包括以下几个:
ParseCommandLine
的实现,也可以添加一些参数,辅助测试,比如对于一些嵌入式数据库,往往需要指定数据库数据存放的路径。Workload
参数加载函数ParseCommandLine
还会从-P
参数传入的文件中读取YCSB测试工作负载的参数。这部分是代码框架本来就实现的。
文件core/core_workload.h
包含YCSB工作负载属性设置的逻辑。包含:
-table tablename:YCSB测试所操作的表的名字,默认为“usertable”
-recordcount n:记录(key-value)个数n
-keylength n:key的长度n
-fieldlength n:字段(相当于列)取值的长度n
-fieldcount n:字段的个数n
-field_len_dist:字段长度分布的方式,选项包括:“uniform”, “zipfian” (有利于简短记录), 和 “constant”,默认为“constant”
-operationcount n:操作的个数n
-readallfields:用于决定是读取记录的一个字段(false)还是读取所有字段(true)的属性名称。
-readproportion f:读操作的比例f,如0.5
-updateproportion f:更新操作的比例
-scanproportion f:范围查找操作的比例
-insertproportion f:插入操作的比例
-requestdistribution op:key请求的分配方式,选项包括:“uniform”, “zipfian” 和 “latest”,默认为“uniform”
-maxscanlength n:范围查找的最大长度(记录数),默认是1000
-scanlengthdistribution:范围查找长度的分配方式,选项包括:“uniform”, “zipfian” (有利于简短记录)。默认为“uniform”
上面只是罗列一些主要的参数选项,更详细的参数选项,参考文件core/core_workload.h
和core/core_workload.cc
文件,里面有相应的注释说明。
从函数ParseCommandLine
的实现逻辑,可以得到负载属性设置文件的书写格数如下:
keylength=16
#
符号对行注释下面是负载属性设置文件的一个例子:
# Yahoo! Cloud System Benchmark
# Workload A: Update heavy workload
# Application example: Session store recording recent actions
#
# Read/update ratio: 50/50
# Default data size: 1 KB records (10 fields, 100 bytes each, plus key)
# Request distribution: zipfian
keylength=16
fieldcount=1
fieldlength=16
# 共3.2GB
recordcount=100000000
operationcount=10000000
workload=com.yahoo.ycsb.workloads.CoreWorkload
readallfields=true
readproportion=0.5
updateproportion=0.5
scanproportion=0
insertproportion=0
requestdistribution=zipfian
负载属性设置文件均放置在目录./wordloads
下,且文件均以.spec
结尾(实际上,任何后缀名的文本文件都可以)。
实际测试的运行由DelegateClient
函数实现。声明如下:
int DelegateClient(ycsbc::DB *db, ycsbc::CoreWorkload *wl, const int num_ops, bool is_loading)
其中
ycsbc::DB *db
通过之前所说的db/db_factory.cc
文件的CreateDB
方法创建。ycsbc::CoreWorkload *wl
通过存放参数的类utils::Properties
来初始化:wl.Init(props)
,是有关负载属性设置的类。num_ops
表示操作的总次数is_loading
指定当前是否是数据加载操作。DelegateClient
函数根据参数情况,执行num_ops
次数的数据加载操作,或者num_ops
次数的测试操作,具体如何测试由参数wl
决定。
更具体的实现逻辑在目录./core
下,想了解具体如何实现的可以进一步细看。
通过创建多线程执行DelegateClient
函数,可以模拟多并发的过程,该函数会在全局变量数组temp_cnt
和temp_time
中保存不同类型操作的次数和所花的时间。
编译程序后,将生成可执行文件ycsbc
。
下面是在我的代码下(mac系统),为RocksDB
实现的YCSB测试的执行示例:
(如何在Mac系统安装RocksDB,可以参考我写的文章:RocksDB使用入门 Mac)
./ycsbc -db rocksdb -dbpath /tmp/rocksdb-test -threads 4 -P "workloads/workloada.spec" -load true -run true
zzh@zzhdeMBP YCSB-HWDB % ./ycsbc -db rocksdb -dbpath /tmp/rocksdb-test -threads 4 -P "workloads/workloada.spec" -load true -run true
---- dbname:rocksdb dbpath:/tmp/rocksdb-test ----
dbname:rocksdb
dboption:0
dbpath:/tmp/rocksdb-test
dbstatistics:false
dbwaitforbalance:false
fieldcount:1
fieldlength:16
insertproportion:0
keylength:16
load:true
morerun:
operationcount:100000
readallfields:true
readproportion:0.5
recordcount:100000
requestdistribution:zipfian
run:true
scanproportion:0
threadcount:4
updateproportion:0.5
workload:com.yahoo.ycsb.workloads.CoreWorkload
----------------------------------------
********** load result **********
loading records:100000 use time:0.397 s IOPS:251946.29 iops (3.97 us/op)
*********************************
********** run result **********
all opeartion records:100000 use time:0.260 s IOPS:384455.69 iops (2.60 us/op)
read ops : 50182 use time: 0.199 s IOPS:252622.78 iops (3.96 us/op)
update ops: 49818 use time: 0.831 s IOPS:59946.65 iops (16.68 us/op)
********************************
zzh@zzhdeMBP YCSB-HWDB %