26 static const char* FLAGS_benchmarks =
41 static int FLAGS_num = 1000000;
44 static int FLAGS_reads = -1;
47 static int FLAGS_value_size = 100;
51 static double FLAGS_compression_ratio = 0.5;
54 static bool FLAGS_histogram =
false;
57 static int FLAGS_cache_size = 4194304;
60 static int FLAGS_page_size = 1024;
65 static bool FLAGS_use_existing_db =
false;
69 static bool FLAGS_compression =
true;
72 static const char* FLAGS_db = NULL;
75 static void DBSynchronize(kyotocabinet::TreeDB*
db_)
78 if (!db_->synchronize()) {
79 fprintf(stderr,
"synchronize error: %s\n", db_->error().name());
87 class RandomGenerator {
99 while (data_.size() < 1048576) {
108 Slice Generate(
int len) {
109 if (pos_ + len > data_.size()) {
111 assert(len < data_.size());
114 return Slice(data_.data() + pos_ - len, len);
118 static Slice TrimSpace(Slice s) {
120 while (start < s.size() && isspace(s[start])) {
123 int limit = s.size();
124 while (limit > start && isspace(s[limit-1])) {
127 return Slice(s.data() +
start, limit -
start);
134 kyotocabinet::TreeDB*
db_;
143 RandomGenerator
gen_;
145 kyotocabinet::LZOCompressor<kyotocabinet::LZO::RAW>
comp_;
152 const int kKeySize = 16;
154 fprintf(stdout,
"Keys: %d bytes each\n", kKeySize);
155 fprintf(stdout,
"Values: %d bytes each (%d bytes after compression)\n",
157 static_cast<int>(FLAGS_value_size * FLAGS_compression_ratio + 0.5));
158 fprintf(stdout,
"Entries: %d\n", num_);
159 fprintf(stdout,
"RawSize: %.1f MB (estimated)\n",
160 ((static_cast<int64_t>(kKeySize + FLAGS_value_size) * num_)
162 fprintf(stdout,
"FileSize: %.1f MB (estimated)\n",
163 (((kKeySize + FLAGS_value_size * FLAGS_compression_ratio) * num_)
166 fprintf(stdout,
"------------------------------------------------\n");
170 #if defined(__GNUC__) && !defined(__OPTIMIZE__)
172 "WARNING: Optimization is disabled: benchmarks unnecessarily slow\n"
177 "WARNING: Assertions are enabled; benchmarks unnecessarily slow\n");
182 fprintf(stderr,
"Kyoto Cabinet: version %s, lib ver %d, lib rev %d\n",
183 kyotocabinet::VERSION, kyotocabinet::LIBVER, kyotocabinet::LIBREV);
186 time_t now = time(NULL);
187 fprintf(stderr,
"Date: %s", ctime(&now));
189 FILE* cpuinfo = fopen(
"/proc/cpuinfo",
"r");
190 if (cpuinfo != NULL) {
193 std::string cpu_type;
194 std::string cache_size;
195 while (fgets(line,
sizeof(line), cpuinfo) != NULL) {
196 const char* sep = strchr(line,
':');
200 Slice key = TrimSpace(
Slice(line, sep - 1 - line));
202 if (key ==
"model name") {
205 }
else if (key ==
"cache size") {
210 fprintf(stderr,
"CPU: %d * %s\n", num_cpus, cpu_type.c_str());
211 fprintf(stderr,
"CPUCache: %s\n", cache_size.c_str());
227 if (FLAGS_histogram) {
231 if (micros > 20000) {
232 fprintf(stderr,
"long op: %.1f micros%30s\r", micros,
"");
235 last_op_finish_ = now;
239 if (done_ >= next_report_) {
240 if (next_report_ < 1000) next_report_ += 100;
241 else if (next_report_ < 5000) next_report_ += 500;
242 else if (next_report_ < 10000) next_report_ += 1000;
243 else if (next_report_ < 50000) next_report_ += 5000;
244 else if (next_report_ < 100000) next_report_ += 10000;
245 else if (next_report_ < 500000) next_report_ += 50000;
246 else next_report_ += 100000;
247 fprintf(stderr,
"... finished %d ops%30s\r", done_,
"");
257 if (done_ < 1) done_ = 1;
261 snprintf(rate,
sizeof(rate),
"%6.1f MB/s",
262 (bytes_ / 1048576.0) / (finish - start_));
263 if (!message_.empty()) {
264 message_ = std::string(rate) +
" " +
message_;
270 fprintf(stdout,
"%-12s : %11.3f micros/op;%s%s\n",
272 (finish -
start_) * 1e6 / done_,
273 (message_.empty() ?
"" :
" "),
275 if (FLAGS_histogram) {
276 fprintf(stdout,
"Microseconds per op:\n%s\n", hist_.
ToString().c_str());
294 reads_(FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads),
297 std::vector<std::string> files;
298 std::string test_dir;
301 if (!FLAGS_use_existing_db) {
302 for (
int i = 0; i < files.size(); i++) {
304 std::string file_name(test_dir);
306 file_name += files[i];
315 fprintf(stderr,
"close error: %s\n", db_->error().name());
323 const char* benchmarks = FLAGS_benchmarks;
324 while (benchmarks != NULL) {
325 const char* sep = strchr(benchmarks,
',');
331 name =
Slice(benchmarks, sep - benchmarks);
332 benchmarks = sep + 1;
338 bool write_sync =
false;
339 if (name ==
Slice(
"fillseq")) {
342 }
else if (name ==
Slice(
"fillrandom")) {
345 }
else if (name ==
Slice(
"overwrite")) {
348 }
else if (name ==
Slice(
"fillrandsync")) {
352 }
else if (name ==
Slice(
"fillseqsync")) {
356 }
else if (name ==
Slice(
"fillrand100K")) {
359 }
else if (name ==
Slice(
"fillseq100K")) {
362 }
else if (name ==
Slice(
"readseq")) {
364 }
else if (name ==
Slice(
"readrandom")) {
366 }
else if (name ==
Slice(
"readrand100K")) {
371 }
else if (name ==
Slice(
"readseq100K")) {
378 if (name !=
Slice()) {
379 fprintf(stderr,
"unknown benchmark '%s'\n", name.
ToString().c_str());
393 db_ =
new kyotocabinet::TreeDB();
396 std::string test_dir;
398 snprintf(file_name,
sizeof(file_name),
399 "%s/dbbench_polyDB-%d.kct",
404 int open_options = kyotocabinet::PolyDB::OWRITER |
405 kyotocabinet::PolyDB::OCREATE;
406 int tune_options = kyotocabinet::TreeDB::TSMALL |
407 kyotocabinet::TreeDB::TLINEAR;
408 if (FLAGS_compression) {
409 tune_options |= kyotocabinet::TreeDB::TCOMPRESS;
410 db_->tune_compressor(&comp_);
412 db_->tune_options(tune_options);
413 db_->tune_page_cache(FLAGS_cache_size);
414 db_->tune_page(FLAGS_page_size);
415 db_->tune_map(256LL<<20);
417 open_options |= kyotocabinet::PolyDB::OAUTOSYNC;
419 if (!db_->open(file_name, open_options)) {
420 fprintf(stderr,
"open error: %s\n", db_->error().name());
425 int num_entries,
int value_size,
int entries_per_batch) {
427 if (state ==
FRESH) {
428 if (FLAGS_use_existing_db) {
429 message_ =
"skipping (--use_existing_db is true)";
438 if (num_entries != num_) {
440 snprintf(msg,
sizeof(msg),
"(%d ops)", num_entries);
445 for (
int i = 0; i < num_entries; i++)
447 const int k = (order ==
SEQUENTIAL) ? i : (rand_.
Next() % num_entries);
449 snprintf(key,
sizeof(key),
"%016d", k);
450 bytes_ += value_size + strlen(key);
451 std::string cpp_key = key;
452 if (!db_->set(cpp_key, gen_.Generate(value_size).ToString())) {
453 fprintf(stderr,
"set error: %s\n", db_->error().name());
460 kyotocabinet::DB::Cursor* cur = db_->cursor();
462 std::string ckey, cvalue;
463 while (cur->get(&ckey, &cvalue,
true)) {
464 bytes_ += ckey.size() + cvalue.size();
472 for (
int i = 0; i <
reads_; i++) {
475 snprintf(key,
sizeof(key),
"%016d", k);
476 db_->get(key, &value);
484 int main(
int argc,
char** argv) {
485 std::string default_db_path;
486 for (
int i = 1; i < argc; i++) {
491 FLAGS_benchmarks = argv[i] + strlen(
"--benchmarks=");
492 }
else if (sscanf(argv[i],
"--compression_ratio=%lf%c", &d, &junk) == 1) {
493 FLAGS_compression_ratio = d;
494 }
else if (sscanf(argv[i],
"--histogram=%d%c", &n, &junk) == 1 &&
495 (n == 0 || n == 1)) {
497 }
else if (sscanf(argv[i],
"--num=%d%c", &n, &junk) == 1) {
499 }
else if (sscanf(argv[i],
"--reads=%d%c", &n, &junk) == 1) {
501 }
else if (sscanf(argv[i],
"--value_size=%d%c", &n, &junk) == 1) {
502 FLAGS_value_size = n;
503 }
else if (sscanf(argv[i],
"--cache_size=%d%c", &n, &junk) == 1) {
504 FLAGS_cache_size = n;
505 }
else if (sscanf(argv[i],
"--page_size=%d%c", &n, &junk) == 1) {
507 }
else if (sscanf(argv[i],
"--compression=%d%c", &n, &junk) == 1 &&
508 (n == 0 || n == 1)) {
509 FLAGS_compression = (n == 1) ?
true :
false;
510 }
else if (strncmp(argv[i],
"--db=", 5) == 0) {
511 FLAGS_db = argv[i] + 5;
513 fprintf(stderr,
"Invalid flag '%s'\n", argv[i]);
519 if (FLAGS_db == NULL) {
521 default_db_path +=
"/dbbench";
522 FLAGS_db = default_db_path.c_str();
virtual Status DeleteFile(const std::string &fname)=0
bool starts_with(const Slice &x) const
int main(int argc, char **argv)
Slice CompressibleString(Random *rnd, double compressed_fraction, int len, std::string *dst)
virtual Status GetChildren(const std::string &dir, std::vector< std::string > *result)=0
std::string ToString() const
kyotocabinet::TreeDB * db_
virtual Status GetTestDirectory(std::string *path)=0
void Write(bool write_sync, Order order, DBState state, int num_entries, int value_size, int entries_per_batch)
void Stop(const Slice &name)
void Write(bool sync, Order order, DBState state, int num_entries, int value_size, int entries_per_batch)
std::string ToString() const
kyotocabinet::LZOCompressor< kyotocabinet::LZO::RAW > comp_
virtual uint64_t NowMicros()=0