LevelDB和ForestDB简单性能测试(含代码)
测试环境简单说明
Windows下测试
硬件环境如下:
处理器:Intel(R) Core(TM) i5-4460 CPU @ 3.20GHz
内 存:8GB
硬 盘:希捷 ST1000DM003
操作系统:Windows 10 企业版
编译说明:
两个都是使用VS2015编译的64位Release版本。运行时库采用动态多线程版本(MD)
Linux下测试
硬件环境如下:
处理器:Intel(R) Core(TM) i7-4500U CPU @ 1.80GHz
内 存:8GB
硬 盘:金士顿64G SSD
操作系统:ArchLinux (Linux version 4.8.13-1-ARCH)
编译说明:
两个都是使用Gcc 6.2.1编译的x64版本,使用-O2参数优化。
测试结果
对LevelDB和ForestDB进行简单的性能测试。
两个都在单线程下进行10000次的增删查改测试,共测试5次。(这里测试的次数有点少,应该测试十万次以上的)
测试的时候可以发现(设置断点),Forest每次操作都将数据缓存在内存了,内存占用比较大。而LevelDB在添加的时候并没有缓存,但是在数据获取和修改的时候内存会变大。
总体上LevelDB占用内存小一点,但是linux下速度不及ForestDB(非常接近)。易用程度上,LevelB简单得多。磁盘占用的情况的话,Forest对磁盘使用比较少,这10000条数据占了13MB左右,而LevelDB则占了120MB左右。
Windows下测试结果
测试结果平均值对比直方图:

LevelDB 测试结果截图

ForestDB 测试结果截图

Linux下测试结果
测试结果平均值对比直方图:

LevelDB 测试结果截图

ForestDB 测试结果截图

测试代码
LevelDB测试代码
#include <cassert>
#include <string>
#include <iostream>
#include <chrono>
#include "leveldb/db.h"
#define TEST_FREQUENCY (10000)
char* randomstr()
{
static char buf[1024];
int len = rand() % 768 + 255;
for (int i = 0; i < len; ++i) {
buf[i] = 'A' + rand() % 26;
}
buf[len] = '\0';
return buf;
}
int main()
{
leveldb::DB* db;
leveldb::Options options;
options.create_if_missing = true;
// 打开数据库
leveldb::Status status = leveldb::DB::Open(options, "./testdb", &db);
assert(status.ok());
srand(2017);
std::string k[TEST_FREQUENCY];
for (int i = 0; i < TEST_FREQUENCY; ++i) {
k[i] = (randomstr());
}
std::string v("壹贰叁肆伍陆柒捌玖拾");
v.append(v).append(v).append(v).append(v).append(v);
// 测试添加
{
auto start = std::chrono::system_clock::now();
for (int i = 0; i < TEST_FREQUENCY; ++i) {
status = db->Put(leveldb::WriteOptions(), k[i], v);
assert(status.ok());
}
auto end = std::chrono::system_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << TEST_FREQUENCY <<"次添加耗时: "
<< double(duration.count()) * std::chrono::microseconds::period::num / std::chrono::microseconds::period::den
<< "秒" << std::endl;
}
// 测试获取
{
auto start = std::chrono::system_clock::now();
std::string v2[TEST_FREQUENCY];
for (int i = 0; i < TEST_FREQUENCY; ++i) {
status = db->Get(leveldb::ReadOptions(), k[i], &v2[i]);
assert(status.ok());
}
auto end = std::chrono::system_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << TEST_FREQUENCY <<"次获取耗时: "
<< double(duration.count()) * std::chrono::microseconds::period::num / std::chrono::microseconds::period::den
<< "秒" << std::endl;
// 验证获取结果是否正确
std::string ss;
for (int i = 0; i < TEST_FREQUENCY; ++i) {
if (v2[i] != v) {
std::cout << "第 " << i << " 个结果不正确" << std::endl;
std::cout << v2[i] << std::endl;
}
}
}
// 测试修改
{
auto start = std::chrono::system_clock::now();
v.append(v);
for (int i = 0; i < TEST_FREQUENCY; ++i) {
status = db->Put(leveldb::WriteOptions(), k[i], v);
assert(status.ok());
}
auto end = std::chrono::system_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << TEST_FREQUENCY <<"次修改耗时: "
<< double(duration.count()) * std::chrono::microseconds::period::num / std::chrono::microseconds::period::den
<< "秒" << std::endl;
}
// 测试删除
{
auto start = std::chrono::system_clock::now();
for (int i = 0; i < TEST_FREQUENCY; ++i) {
status = db->Delete(leveldb::WriteOptions(), k[i]);
assert(status.ok());
}
auto end = std::chrono::system_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << TEST_FREQUENCY <<"次删除耗时: "
<< double(duration.count()) * std::chrono::microseconds::period::num / std::chrono::microseconds::period::den
<< "秒" << std::endl;
}
delete db;
return 0;
}
Forest 测试代码
#include <cassert>
#include <string>
#include <iostream>
#include <chrono>
#include "libforestdb/forestdb.h"
#define TEST_FREQUENCY (10000)
char* randomstr()
{
static char buf[1024];
int len = rand() % 768 + 255;
for (int i = 0; i < len; ++i) {
buf[i] = 'A' + rand() % 26;
}
buf[len] = '\0';
return buf;
}
int main()
{
fdb_file_handle* fdbFileHandle = nullptr;
fdb_kvs_handle* fdbKvsHandle = nullptr;
fdb_status status;
// 初始化ForestDB
// 1、文件配置设置配置
fdb_config fileConfig = fdb_get_default_config();
{// WAL阈值4K
fileConfig.wal_threshold = 4096;
// 缓存大小64MB
fileConfig.buffercache_size = 64 * 1024 * 1024;
// 设置使用默认的kvs
fileConfig.multi_kv_instances = false;
// 关闭循环块复用
fileConfig.block_reusing_threshold = 100;
// 使用序列树
fileConfig.seqtree_opt = FDB_SEQTREE_USE;
}
// 2、使用设置的配置进行初始化
status = fdb_init(&fileConfig);
assert(status == FDB_RESULT_SUCCESS);
// 打开数据库
status = fdb_open(&fdbFileHandle, "./testdb", &fileConfig);
assert(status == FDB_RESULT_SUCCESS);
// 打开kvs
fdb_kvs_config kvsConfig = fdb_get_default_kvs_config();
status = fdb_kvs_open_default(fdbFileHandle, &fdbKvsHandle, &kvsConfig);
assert(status == FDB_RESULT_SUCCESS);
srand(2017);
std::string k[TEST_FREQUENCY];
for (int i = 0; i < TEST_FREQUENCY; ++i) {
k[i] = (randomstr());
}
std::string v("壹贰叁肆伍陆柒捌玖拾");
v.append(v).append(v).append(v).append(v).append(v);
// 测试添加
{
auto start = std::chrono::system_clock::now();
for (int i = 0; i < TEST_FREQUENCY; ++i) {
status = fdb_set_kv(fdbKvsHandle, k[i].data(), k[i].size(), v.data(), v.size());
assert(status == FDB_RESULT_SUCCESS);
}
// 提交操作到磁盘(这里必须commit才能实际写入到磁盘)
fdb_commit(fdbFileHandle, FDB_COMMIT_NORMAL);
auto end = std::chrono::system_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << TEST_FREQUENCY <<"次添加耗时: "
<< double(duration.count()) * std::chrono::microseconds::period::num / std::chrono::microseconds::period::den
<< "秒" << std::endl;
}
// 测试获取
{
auto start = std::chrono::system_clock::now();
void* v2[TEST_FREQUENCY]; size_t v2len[TEST_FREQUENCY];
for (int i = 0; i < TEST_FREQUENCY; ++i) {
status = fdb_get_kv(fdbKvsHandle, k[i].data(), k[i].size(), &v2[i], &v2len[i]);
assert(status == FDB_RESULT_SUCCESS);
}
auto end = std::chrono::system_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << TEST_FREQUENCY <<"次获取耗时: "
<< double(duration.count()) * std::chrono::microseconds::period::num / std::chrono::microseconds::period::den
<< "秒" << std::endl;
// 验证获取结果是否正确
std::string ss;
for (int i = 0; i < TEST_FREQUENCY; ++i) {
ss.assign((const char*)v2[i], v2len[i]);
if (ss != v) {
std::cout << "第 " << i << " 个结果不正确" << std::endl;
std::cout << ss << std::endl;
}
free(v2[i]);
}
}
// 测试修改
{
auto start = std::chrono::system_clock::now();
v.append(v);
for (int i = 0; i < TEST_FREQUENCY; ++i) {
status = fdb_set_kv(fdbKvsHandle, k[i].data(), k[i].size(), v.data(), v.size());
assert(status == FDB_RESULT_SUCCESS);
}
// 提交操作到磁盘(这里必须commit才能实际写入到磁盘)
fdb_commit(fdbFileHandle, FDB_COMMIT_NORMAL);
auto end = std::chrono::system_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << TEST_FREQUENCY <<"次修改耗时: "
<< double(duration.count()) * std::chrono::microseconds::period::num / std::chrono::microseconds::period::den
<< "秒" << std::endl;
}
// 测试删除
{
auto start = std::chrono::system_clock::now();
for (int i = 0; i < TEST_FREQUENCY; ++i) {
status = fdb_del_kv(fdbKvsHandle, k[i].data(), k[i].size());
assert(status == FDB_RESULT_SUCCESS);
}
// 提交操作到磁盘(这里必须commit才能实际写入到磁盘)
fdb_commit(fdbFileHandle, FDB_COMMIT_NORMAL);
auto end = std::chrono::system_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << TEST_FREQUENCY <<"次删除耗时: "
<< double(duration.count()) * std::chrono::microseconds::period::num / std::chrono::microseconds::period::den
<< "秒" << std::endl;
}
// 关闭数据库
status = fdb_kvs_close(fdbKvsHandle);
assert(status == FDB_RESULT_SUCCESS);
status = fdb_close(fdbFileHandle);
assert(status == FDB_RESULT_SUCCESS);
status = fdb_shutdown();
assert(status == FDB_RESULT_SUCCESS);
return 0;
}
LevelDB和ForestDB简单性能测试(含代码)的更多相关文章
- Linux下RocksDB、LevelDB、ForestDB性能测试对比
简要说明 本次环境与http://www.cnblogs.com/oloroso/p/6306352.html中的一致. 依然是增删查改各测试10000次,每个测试重复5次取平均值. 1.不使用jem ...
- .Net core2.0日志组件Log4net、Nlog简单性能测试
.Net core之Log4net.Nlog简单性能测试 比较log4net.nlog的文件写入性能(.netcore环境),涉及代码和配置如有不正确的地方,还请批评指正. 原创,转载请著名出处:ht ...
- snaic和tornado的简单性能测试
操作系统 : CentOS7.3.1611_x64 Python 版本 : 3.6.8 tornado版本:6.0.2 snaic版本:19.9.0 CPU : Intel(R) Core(TM) i ...
- HTML QQ聊天代码 简单的一行代码
简单的一行代码: <a href="tencent://message/?uin=173007740&Site=&Menu=yes">和17300774 ...
- qt简单界面更新代码(菜鸟级)(部分代码)
qt简单界面更新代码(菜鸟级)(部分代码)self.timers_1=QtCore.QTimer(self)self.timers_1.timeout.connect(self.min_1)self. ...
- Greenplum 简单性能测试与分析
如今,多样的交易模式以及大众消费观念的改变使得数据库应用领域不断扩大,现代的大型分布式应用系统的数据膨胀也对数据库的海量数据处理能力和并行处理能力提出了更高的要求,如何在数据呈现海量扩张的同时提高处理 ...
- Spring源码学习:第1步--在Spring源码中添加最简单的Demo代码
为了最大程度地贴近Spring源码并进行学习,一种比较直接的做法是:直接在Spring源码中加入Demo代码,并进行调试. 参照以前使用Spring的经验,Spring最简单的使用方法是:一个实体类. ...
- Flume1.9.0的安装、部署、简单应用(含分布式、与Hadoop3.1.2、Hbase1.4.9的案例)
目录 目录 前言 什么是Flume? Flume的特点 Flume的可靠性 Flume的可恢复性 Flume的一些核心概念 Flume的官方网站在哪里? Flume在哪里下载以及如何安装? 设置环境变 ...
- JS实现简单的运行代码 & 侧边广告
/* JS实现简单的运行代码功能 */<!doctype html> <html> <head> <meta charset="utf-8" ...
随机推荐
- yolo源码解析(二)
五 读取数据pascal_voc.py文件解析 我们在YOLENet类中定义了两个占位符,一个是输入图片占位符,一个是图片对应的标签占位符,如下: #输入图片占位符 [NONE,image_size, ...
- EF更新指定字段.或个更新整个实体
EF更新指定字段.或个更新整个实体 更新整个实体: public bool Update(Company compay) { if (compay != null) { dbContext.Entry ...
- Unicode和UTF-8之间的关系
作者: 阮一峰 日期: 2007年10月28日 今天中午,我突然想搞清楚Unicode和UTF-8之间的关系,于是就开始在网上查资料. 结果,这个问题比我想象的复杂,从午饭后一直看到晚上9点,才算初步 ...
- 使用Log4j将程序日志实时写入Kafka(转)
原文链接:使用Log4j将程序日志实时写入Kafka 很多应用程序使用Log4j记录日志,如何使用Kafka实时的收集与存储这些Log4j产生的日志呢?一种方案是使用其他组件(比如Flume,或者自己 ...
- hyper-v 尝试更改 状态时 应用程序遇到错误 无法初始化
刚还原了一个问题,现在 又来一个: 让我崩溃的微软 hyper-v.这次错误 提示也没了. http://social.technet.microsoft.com/Forums/de-DE/751b2 ...
- warning: LF will be replaced by CRLF in dubbo-demo-api/pom.xml.
今天使用git add .的时候出现了一个错误. 错误如下: 解决方案: $ rm -rf .git // 删除.git $ git config --global core.autocrlf fal ...
- WebFormViewEngine及用户控件寻址bug
在做我的网站的时候遇到了主题切换的问题,特总结与大家共享. 熟悉asp.net mvc的朋友都知道,mvc中,默认情况下视图都在views文件夹下放着.要想改变文件必须重写WebFormViewEng ...
- Android ActionBar使用介绍
一.什么是ActionBar 有图有真相,看一下图片就了解的差不多了 对于大多数应用,操作栏可以分割为 4 个不同的功能区域. 1. 应用图标 应用图标是您应用的标志.在应用图标位置摆放您自己的 lo ...
- Python实现爬虫设置代理IP和伪装成浏览器的方法(转载)
https://www.jb51.net/article/139587.htm chrome_options = webdriver.ChromeOptions() chrome_options.ad ...
- [干货]Kaggle热门 | 用一个框架解决所有机器学习难题
新智元推荐 来源:LinkedIn 作者:Abhishek Thakur 译者:弗格森 [新智元导读]本文是数据科学家Abhishek Thakur发表的Kaggle热门文章.作者总结了自己参加100 ...