1179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Use of this source code is governed by a BSD-style license that can be
3179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// found in the LICENSE file. See the AUTHORS file for names of contributors.
4179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
5179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include <sys/types.h>
6179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include <stdio.h>
7179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include <stdlib.h>
8179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "db/db_impl.h"
9179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "db/version_set.h"
10fbd97aa4c5325eace57d24b89845b9581bac9324jorlow@chromium.org#include "leveldb/cache.h"
11fbd97aa4c5325eace57d24b89845b9581bac9324jorlow@chromium.org#include "leveldb/db.h"
12fbd97aa4c5325eace57d24b89845b9581bac9324jorlow@chromium.org#include "leveldb/env.h"
13fbd97aa4c5325eace57d24b89845b9581bac9324jorlow@chromium.org#include "leveldb/write_batch.h"
14225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org#include "port/port.h"
15225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org#include "util/crc32c.h"
16179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "util/histogram.h"
17d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com#include "util/mutexlock.h"
18179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "util/random.h"
19179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org#include "util/testutil.h"
20179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
21179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Comma-separated list of operations to run in the specified order
22179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org//   Actual benchmarks:
23b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org//      fillseq       -- write N values in sequential key order in async mode
24b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org//      fillrandom    -- write N values in random key order in async mode
25b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org//      overwrite     -- overwrite N values in random key order in async mode
26b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org//      fillsync      -- write N/100 values in random key order in sync mode
27b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org//      fill100K      -- write N/1000 100K values in random order in async mode
2899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com//      deleteseq     -- delete N keys in sequential order
2999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com//      deleterandom  -- delete N keys in random order
30a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org//      readseq       -- read N times sequentially
31a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org//      readreverse   -- read N times in reverse order
32a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org//      readrandom    -- read N times in random order
3399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com//      readmissing   -- read N missing keys in random order
34a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org//      readhot       -- read N times in random order from 1% section of DB
3599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com//      seekrandom    -- N random seeks
36225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org//      crc32c        -- repeated crc32c of 4K of data
37c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org//      acquireload   -- load N*1000 times
38179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org//   Meta operations:
39179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org//      compact     -- Compact the entire DB
4095e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org//      stats       -- Print DB stats
4199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com//      sstables    -- Print sstable info
42179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org//      heapprofile -- Dump a heap profile (if supported by this port)
43179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstatic const char* FLAGS_benchmarks =
44b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    "fillseq,"
45225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org    "fillsync,"
46b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    "fillrandom,"
47b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    "overwrite,"
48225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org    "readrandom,"
49225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org    "readrandom,"  // Extra run to allow previous compactions to quiesce
50179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    "readseq,"
5184744ee8e3e568ca5b24eabf31be706d69d80c4djorlow@chromium.org    "readreverse,"
52179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    "compact,"
53225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org    "readrandom,"
54179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    "readseq,"
5584744ee8e3e568ca5b24eabf31be706d69d80c4djorlow@chromium.org    "readreverse,"
56225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org    "fill100K,"
57225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org    "crc32c,"
5895e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    "snappycomp,"
5995e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    "snappyuncomp,"
60c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org    "acquireload,"
61225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org    ;
62179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
63179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Number of key/values to place in database
64179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstatic int FLAGS_num = 1000000;
65179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
66a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org// Number of read operations to do.  If negative, do FLAGS_num reads.
67a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.orgstatic int FLAGS_reads = -1;
68a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org
69d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com// Number of concurrent threads to run.
70d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.comstatic int FLAGS_threads = 1;
71d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
72179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Size of each value
73179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstatic int FLAGS_value_size = 100;
74179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
75179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Arrange to generate values that shrink to this fraction of
76179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// their original size after compression
77b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.orgstatic double FLAGS_compression_ratio = 0.5;
78179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
79179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Print histogram of operation timings
80179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgstatic bool FLAGS_histogram = false;
81179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
82179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org// Number of bytes to buffer in memtable before compacting
8395e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org// (initialized to default value by "main")
8495e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.orgstatic int FLAGS_write_buffer_size = 0;
8595e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org
8695e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org// Number of bytes to use as a cache of uncompressed data.
8795e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org// Negative means use default settings.
8895e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.orgstatic int FLAGS_cache_size = -1;
89179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
90a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org// Maximum number of files to keep open at the same time (use default if == 0)
91a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.orgstatic int FLAGS_open_files = 0;
92a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org
9399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com// Bloom filter bits per key.
9499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com// Negative means use default settings.
9599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.comstatic int FLAGS_bloom_bits = -1;
9699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
97a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org// If true, do not destroy the existing database.  If you set this
98a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org// flag and also specify a benchmark that wants a fresh database, that
99a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org// benchmark will fail.
100a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.orgstatic bool FLAGS_use_existing_db = false;
101a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org
1028cd4ab8303620197cf24282ae8639060efbb326egabor@google.com// Use the db with the following name.
103158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.comstatic const char* FLAGS_db = NULL;
1048cd4ab8303620197cf24282ae8639060efbb326egabor@google.com
105179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgnamespace leveldb {
106179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
107179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgnamespace {
108d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
109d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com// Helper for quickly generating random data.
110179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgclass RandomGenerator {
111179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org private:
112179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  std::string data_;
113179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  int pos_;
114179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
115179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org public:
116179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  RandomGenerator() {
117179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    // We use a limited amount of data over and over again and ensure
118179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    // that it is larger than the compression window (32KB), and also
119179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    // large enough to serve all typical value sizes we want to write.
120179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    Random rnd(301);
121179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    std::string piece;
122179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    while (data_.size() < 1048576) {
123179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      // Add a short fragment that is as compressible as specified
124179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      // by FLAGS_compression_ratio.
125179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      test::CompressibleString(&rnd, FLAGS_compression_ratio, 100, &piece);
126179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      data_.append(piece);
127179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
128179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    pos_ = 0;
129179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
130179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
1314935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  Slice Generate(size_t len) {
132179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    if (pos_ + len > data_.size()) {
133179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      pos_ = 0;
134179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      assert(len < data_.size());
135179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
136179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    pos_ += len;
137179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    return Slice(data_.data() + pos_ - len, len);
138179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
139179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org};
140b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org
141b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.orgstatic Slice TrimSpace(Slice s) {
1424935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  size_t start = 0;
143b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  while (start < s.size() && isspace(s[start])) {
144b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    start++;
145b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  }
1464935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org  size_t limit = s.size();
147b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  while (limit > start && isspace(s[limit-1])) {
148b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    limit--;
149b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  }
150b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  return Slice(s.data() + start, limit - start);
151b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org}
152b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org
153d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.comstatic void AppendWithSpace(std::string* str, Slice msg) {
154d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  if (msg.empty()) return;
155d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  if (!str->empty()) {
156d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    str->push_back(' ');
157d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  }
158d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  str->append(msg.data(), msg.size());
159d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com}
160d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
161d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.comclass Stats {
162d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com private:
163d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  double start_;
164d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  double finish_;
165d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  double seconds_;
166d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  int done_;
167d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  int next_report_;
168d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  int64_t bytes_;
169d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  double last_op_finish_;
170d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  Histogram hist_;
171d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  std::string message_;
172d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
173d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com public:
174d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  Stats() { Start(); }
175d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
176d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  void Start() {
177d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    next_report_ = 100;
178d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    last_op_finish_ = start_;
179d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    hist_.Clear();
180d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    done_ = 0;
181d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    bytes_ = 0;
182d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    seconds_ = 0;
183d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    start_ = Env::Default()->NowMicros();
184d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    finish_ = start_;
185d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    message_.clear();
186d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  }
187d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
188d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  void Merge(const Stats& other) {
189d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    hist_.Merge(other.hist_);
190d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    done_ += other.done_;
191d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    bytes_ += other.bytes_;
192d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    seconds_ += other.seconds_;
193d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    if (other.start_ < start_) start_ = other.start_;
194d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    if (other.finish_ > finish_) finish_ = other.finish_;
195d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
196d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    // Just keep the messages from one thread
197d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    if (message_.empty()) message_ = other.message_;
198d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  }
199d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
200d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  void Stop() {
201d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    finish_ = Env::Default()->NowMicros();
202d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    seconds_ = (finish_ - start_) * 1e-6;
203d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  }
204d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
205d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  void AddMessage(Slice msg) {
206d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    AppendWithSpace(&message_, msg);
207d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  }
208d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
209d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  void FinishedSingleOp() {
210d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    if (FLAGS_histogram) {
211d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      double now = Env::Default()->NowMicros();
212d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      double micros = now - last_op_finish_;
213d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      hist_.Add(micros);
214d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      if (micros > 20000) {
215d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        fprintf(stderr, "long op: %.1f micros%30s\r", micros, "");
216d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        fflush(stderr);
217d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      }
218d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      last_op_finish_ = now;
219d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    }
220d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
221d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    done_++;
222d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    if (done_ >= next_report_) {
223d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      if      (next_report_ < 1000)   next_report_ += 100;
224d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      else if (next_report_ < 5000)   next_report_ += 500;
225d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      else if (next_report_ < 10000)  next_report_ += 1000;
226d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      else if (next_report_ < 50000)  next_report_ += 5000;
227d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      else if (next_report_ < 100000) next_report_ += 10000;
228d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      else if (next_report_ < 500000) next_report_ += 50000;
229d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      else                            next_report_ += 100000;
230d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      fprintf(stderr, "... finished %d ops%30s\r", done_, "");
231d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      fflush(stderr);
232d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    }
233d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  }
234d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
235d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  void AddBytes(int64_t n) {
236d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    bytes_ += n;
237d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  }
238d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
239d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  void Report(const Slice& name) {
240d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    // Pretend at least one op was done in case we are running a benchmark
241d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    // that does not call FinishedSingleOp().
242d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    if (done_ < 1) done_ = 1;
243d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
244d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    std::string extra;
245d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    if (bytes_ > 0) {
246d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      // Rate is computed on actual elapsed time, not the sum of per-thread
247d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      // elapsed times.
248d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      double elapsed = (finish_ - start_) * 1e-6;
249d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      char rate[100];
250d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      snprintf(rate, sizeof(rate), "%6.1f MB/s",
251d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com               (bytes_ / 1048576.0) / elapsed);
252d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      extra = rate;
253d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    }
254d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    AppendWithSpace(&extra, message_);
255d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
256d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    fprintf(stdout, "%-12s : %11.3f micros/op;%s%s\n",
257d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com            name.ToString().c_str(),
258d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com            seconds_ * 1e6 / done_,
259d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com            (extra.empty() ? "" : " "),
260d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com            extra.c_str());
261d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    if (FLAGS_histogram) {
262d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      fprintf(stdout, "Microseconds per op:\n%s\n", hist_.ToString().c_str());
263d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    }
264d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    fflush(stdout);
265d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  }
266d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com};
267d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
268d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com// State shared by all concurrent executions of the same benchmark.
269d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.comstruct SharedState {
270d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  port::Mutex mu;
271d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  port::CondVar cv;
272d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  int total;
273d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
274d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  // Each thread goes through the following states:
275d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  //    (1) initializing
276d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  //    (2) waiting for others to be initialized
277d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  //    (3) running
278d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  //    (4) done
279d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
280d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  int num_initialized;
281d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  int num_done;
282d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  bool start;
283d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
284d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  SharedState() : cv(&mu) { }
285d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com};
286d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
287d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com// Per-thread state for concurrent executions of the same benchmark.
288d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.comstruct ThreadState {
289d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  int tid;             // 0..n-1 when running in n threads
290d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  Random rand;         // Has different seeds for different threads
291d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  Stats stats;
292394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com  SharedState* shared;
293d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
294d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  ThreadState(int index)
295d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      : tid(index),
296d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        rand(1000 + index) {
297d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  }
298d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com};
299d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
30045b9940be332834440bd5299419f396e38085ebehans@chromium.org}  // namespace
301179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
302179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgclass Benchmark {
303179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org private:
304179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  Cache* cache_;
30599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  const FilterPolicy* filter_policy_;
306179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  DB* db_;
307179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  int num_;
308d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  int value_size_;
309d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  int entries_per_batch_;
310d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  WriteOptions write_options_;
311a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  int reads_;
312179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  int heap_counter_;
313179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
314b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  void PrintHeader() {
315b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    const int kKeySize = 16;
316b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    PrintEnvironment();
317b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    fprintf(stdout, "Keys:       %d bytes each\n", kKeySize);
318b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    fprintf(stdout, "Values:     %d bytes each (%d bytes after compression)\n",
319b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org            FLAGS_value_size,
320b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org            static_cast<int>(FLAGS_value_size * FLAGS_compression_ratio + 0.5));
321b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    fprintf(stdout, "Entries:    %d\n", num_);
322b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    fprintf(stdout, "RawSize:    %.1f MB (estimated)\n",
32395e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org            ((static_cast<int64_t>(kKeySize + FLAGS_value_size) * num_)
32495e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org             / 1048576.0));
325b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    fprintf(stdout, "FileSize:   %.1f MB (estimated)\n",
326b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org            (((kKeySize + FLAGS_value_size * FLAGS_compression_ratio) * num_)
327b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org             / 1048576.0));
328b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    PrintWarnings();
329b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    fprintf(stdout, "------------------------------------------------\n");
330b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  }
331b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org
332b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  void PrintWarnings() {
333b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org#if defined(__GNUC__) && !defined(__OPTIMIZE__)
334b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    fprintf(stdout,
335b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org            "WARNING: Optimization is disabled: benchmarks unnecessarily slow\n"
336b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org            );
337b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org#endif
338b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org#ifndef NDEBUG
339b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    fprintf(stdout,
340b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org            "WARNING: Assertions are enabled; benchmarks unnecessarily slow\n");
341b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org#endif
34295e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org
34395e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    // See if snappy is working by attempting to compress a compressible string
34495e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    const char text[] = "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy";
34595e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    std::string compressed;
34695e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    if (!port::Snappy_Compress(text, sizeof(text), &compressed)) {
34795e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org      fprintf(stdout, "WARNING: Snappy compression is not enabled\n");
34895e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    } else if (compressed.size() >= sizeof(text)) {
34995e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org      fprintf(stdout, "WARNING: Snappy compression is not effective\n");
35095e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    }
351b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  }
352b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org
353b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  void PrintEnvironment() {
354b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    fprintf(stderr, "LevelDB:    version %d.%d\n",
355b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org            kMajorVersion, kMinorVersion);
356b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org
357b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org#if defined(__linux)
358b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    time_t now = time(NULL);
359b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    fprintf(stderr, "Date:       %s", ctime(&now));  // ctime() adds newline
360b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org
361b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    FILE* cpuinfo = fopen("/proc/cpuinfo", "r");
362b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    if (cpuinfo != NULL) {
363b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      char line[1000];
364b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      int num_cpus = 0;
365b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      std::string cpu_type;
366b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      std::string cache_size;
367b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      while (fgets(line, sizeof(line), cpuinfo) != NULL) {
368b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org        const char* sep = strchr(line, ':');
369b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org        if (sep == NULL) {
370b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org          continue;
371b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org        }
372b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org        Slice key = TrimSpace(Slice(line, sep - 1 - line));
373b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org        Slice val = TrimSpace(Slice(sep + 1));
374b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org        if (key == "model name") {
375b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org          ++num_cpus;
376b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org          cpu_type = val.ToString();
377b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org        } else if (key == "cache size") {
378b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org          cache_size = val.ToString();
379b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org        }
380b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      }
381b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      fclose(cpuinfo);
382b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      fprintf(stderr, "CPU:        %d * %s\n", num_cpus, cpu_type.c_str());
383b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      fprintf(stderr, "CPUCache:   %s\n", cache_size.c_str());
384b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    }
385b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org#endif
386b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  }
387b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org
388179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org public:
38995e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org  Benchmark()
39095e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org  : cache_(FLAGS_cache_size >= 0 ? NewLRUCache(FLAGS_cache_size) : NULL),
39199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    filter_policy_(FLAGS_bloom_bits >= 0
39299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com                   ? NewBloomFilterPolicy(FLAGS_bloom_bits)
39399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com                   : NULL),
39495e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    db_(NULL),
39595e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    num_(FLAGS_num),
396d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    value_size_(FLAGS_value_size),
397d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    entries_per_batch_(1),
398a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    reads_(FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads),
399d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    heap_counter_(0) {
400179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    std::vector<std::string> files;
4018cd4ab8303620197cf24282ae8639060efbb326egabor@google.com    Env::Default()->GetChildren(FLAGS_db, &files);
4024935bf087b28aa308c0a820720b85ef695e236aedgrogan@chromium.org    for (size_t i = 0; i < files.size(); i++) {
403179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      if (Slice(files[i]).starts_with("heap-")) {
4048cd4ab8303620197cf24282ae8639060efbb326egabor@google.com        Env::Default()->DeleteFile(std::string(FLAGS_db) + "/" + files[i]);
405179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      }
406179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
407a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    if (!FLAGS_use_existing_db) {
4088cd4ab8303620197cf24282ae8639060efbb326egabor@google.com      DestroyDB(FLAGS_db, Options());
409a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    }
410179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
411179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
412179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  ~Benchmark() {
413179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    delete db_;
414179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    delete cache_;
41599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    delete filter_policy_;
416179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
417179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
418179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  void Run() {
419b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    PrintHeader();
420b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    Open();
421179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
422179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    const char* benchmarks = FLAGS_benchmarks;
423179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    while (benchmarks != NULL) {
424179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      const char* sep = strchr(benchmarks, ',');
425179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      Slice name;
426179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      if (sep == NULL) {
427179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        name = benchmarks;
428179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        benchmarks = NULL;
429179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      } else {
430179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        name = Slice(benchmarks, sep - benchmarks);
431179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        benchmarks = sep + 1;
432179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      }
433179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
434d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      // Reset parameters that may be overriddden bwlow
435d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      num_ = FLAGS_num;
436394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com      reads_ = (FLAGS_reads < 0 ? FLAGS_num : FLAGS_reads);
437d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      value_size_ = FLAGS_value_size;
438d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      entries_per_batch_ = 1;
439d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      write_options_ = WriteOptions();
440d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
441d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      void (Benchmark::*method)(ThreadState*) = NULL;
442d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      bool fresh_db = false;
443394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com      int num_threads = FLAGS_threads;
444b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org
445b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      if (name == Slice("fillseq")) {
446d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        fresh_db = true;
447d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        method = &Benchmark::WriteSeq;
44895e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org      } else if (name == Slice("fillbatch")) {
449d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        fresh_db = true;
450d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        entries_per_batch_ = 1000;
451d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        method = &Benchmark::WriteSeq;
452b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      } else if (name == Slice("fillrandom")) {
453d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        fresh_db = true;
454d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        method = &Benchmark::WriteRandom;
455b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      } else if (name == Slice("overwrite")) {
456d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        fresh_db = false;
457d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        method = &Benchmark::WriteRandom;
458b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      } else if (name == Slice("fillsync")) {
459d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        fresh_db = true;
460d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        num_ /= 1000;
461d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        write_options_.sync = true;
462d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        method = &Benchmark::WriteRandom;
463b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      } else if (name == Slice("fill100K")) {
464d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        fresh_db = true;
465d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        num_ /= 1000;
466d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        value_size_ = 100 * 1000;
467d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        method = &Benchmark::WriteRandom;
468179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      } else if (name == Slice("readseq")) {
469d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        method = &Benchmark::ReadSequential;
47084744ee8e3e568ca5b24eabf31be706d69d80c4djorlow@chromium.org      } else if (name == Slice("readreverse")) {
471d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        method = &Benchmark::ReadReverse;
472179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      } else if (name == Slice("readrandom")) {
473d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        method = &Benchmark::ReadRandom;
47499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      } else if (name == Slice("readmissing")) {
47599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        method = &Benchmark::ReadMissing;
47699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      } else if (name == Slice("seekrandom")) {
47799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        method = &Benchmark::SeekRandom;
478a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org      } else if (name == Slice("readhot")) {
479d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        method = &Benchmark::ReadHot;
48095e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org      } else if (name == Slice("readrandomsmall")) {
481a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org        reads_ /= 1000;
482d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        method = &Benchmark::ReadRandom;
48399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      } else if (name == Slice("deleteseq")) {
48499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        method = &Benchmark::DeleteSeq;
48599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      } else if (name == Slice("deleterandom")) {
48699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        method = &Benchmark::DeleteRandom;
487394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com      } else if (name == Slice("readwhilewriting")) {
488394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com        num_threads++;  // Add extra thread for writing
489394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com        method = &Benchmark::ReadWhileWriting;
490179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      } else if (name == Slice("compact")) {
491d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        method = &Benchmark::Compact;
492225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org      } else if (name == Slice("crc32c")) {
493d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        method = &Benchmark::Crc32c;
494c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org      } else if (name == Slice("acquireload")) {
495d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        method = &Benchmark::AcquireLoad;
49695e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org      } else if (name == Slice("snappycomp")) {
497d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        method = &Benchmark::SnappyCompress;
49895e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org      } else if (name == Slice("snappyuncomp")) {
499d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        method = &Benchmark::SnappyUncompress;
500179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      } else if (name == Slice("heapprofile")) {
501179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        HeapProfile();
50295e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org      } else if (name == Slice("stats")) {
50399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        PrintStats("leveldb.stats");
50499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      } else if (name == Slice("sstables")) {
50599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        PrintStats("leveldb.sstables");
506179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      } else {
50795e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org        if (name != Slice()) {  // No error message for empty name
50895e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org          fprintf(stderr, "unknown benchmark '%s'\n", name.ToString().c_str());
50995e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org        }
51095e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org      }
511d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
512d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      if (fresh_db) {
513d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        if (FLAGS_use_existing_db) {
514d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com          fprintf(stdout, "%-12s : skipped (--use_existing_db is true)\n",
515d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com                  name.ToString().c_str());
516d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com          method = NULL;
517d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        } else {
518d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com          delete db_;
519d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com          db_ = NULL;
520d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com          DestroyDB(FLAGS_db, Options());
521d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com          Open();
522d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        }
523d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      }
524d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
525d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      if (method != NULL) {
526394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com        RunBenchmark(num_threads, name, method);
527179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      }
528179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
529179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
530179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
531b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org private:
532d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  struct ThreadArg {
533d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    Benchmark* bm;
534d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    SharedState* shared;
535d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    ThreadState* thread;
536d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    void (Benchmark::*method)(ThreadState*);
537d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  };
538d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
539d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  static void ThreadBody(void* v) {
540d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    ThreadArg* arg = reinterpret_cast<ThreadArg*>(v);
541d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    SharedState* shared = arg->shared;
542d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    ThreadState* thread = arg->thread;
543d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    {
544d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      MutexLock l(&shared->mu);
545d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      shared->num_initialized++;
546d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      if (shared->num_initialized >= shared->total) {
547d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        shared->cv.SignalAll();
548d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      }
549d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      while (!shared->start) {
550d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        shared->cv.Wait();
551d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      }
552d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    }
553d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
554d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    thread->stats.Start();
555d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    (arg->bm->*(arg->method))(thread);
556d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    thread->stats.Stop();
557d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
558d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    {
559d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      MutexLock l(&shared->mu);
560d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      shared->num_done++;
561d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      if (shared->num_done >= shared->total) {
562d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        shared->cv.SignalAll();
563d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      }
564d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    }
565d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  }
566d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
567394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com  void RunBenchmark(int n, Slice name,
568394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com                    void (Benchmark::*method)(ThreadState*)) {
569d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    SharedState shared;
570d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    shared.total = n;
571d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    shared.num_initialized = 0;
572d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    shared.num_done = 0;
573d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    shared.start = false;
574d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
575d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    ThreadArg* arg = new ThreadArg[n];
576d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    for (int i = 0; i < n; i++) {
577d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      arg[i].bm = this;
578d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      arg[i].method = method;
579d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      arg[i].shared = &shared;
580d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      arg[i].thread = new ThreadState(i);
581394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com      arg[i].thread->shared = &shared;
582d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      Env::Default()->StartThread(ThreadBody, &arg[i]);
583d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    }
584d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
585d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    shared.mu.Lock();
586d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    while (shared.num_initialized < n) {
587d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      shared.cv.Wait();
588d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    }
589d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
590d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    shared.start = true;
591d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    shared.cv.SignalAll();
592d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    while (shared.num_done < n) {
593d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      shared.cv.Wait();
594d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    }
595d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    shared.mu.Unlock();
596d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
597d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    for (int i = 1; i < n; i++) {
598d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      arg[0].thread->stats.Merge(arg[i].thread->stats);
599d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    }
600d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    arg[0].thread->stats.Report(name);
601d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
602d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    for (int i = 0; i < n; i++) {
603d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      delete arg[i].thread;
604d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    }
605d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    delete[] arg;
606d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  }
607d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
608d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  void Crc32c(ThreadState* thread) {
609225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org    // Checksum about 500MB of data total
610d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    const int size = 4096;
611d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    const char* label = "(4K per op)";
612f85ede82f8c27a00c3120f67fbab89b2a89fe987jorlow@chromium.org    std::string data(size, 'x');
613225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org    int64_t bytes = 0;
614225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org    uint32_t crc = 0;
615225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org    while (bytes < 500 * 1048576) {
616225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org      crc = crc32c::Value(data.data(), size);
617d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      thread->stats.FinishedSingleOp();
618225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org      bytes += size;
619225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org    }
620225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org    // Print so result is not dead
621225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org    fprintf(stderr, "... crc=0x%x\r", static_cast<unsigned int>(crc));
622225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
623d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    thread->stats.AddBytes(bytes);
624d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    thread->stats.AddMessage(label);
625225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org  }
626225a272621a5517a1a8dec8956457a121786d7c4jorlow@chromium.org
627d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  void AcquireLoad(ThreadState* thread) {
628c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org    int dummy;
629c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org    port::AtomicPointer ap(&dummy);
630c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org    int count = 0;
631c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org    void *ptr = NULL;
632d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    thread->stats.AddMessage("(each op is 1000 loads)");
633c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org    while (count < 100000) {
634c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org      for (int i = 0; i < 1000; i++) {
635c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org        ptr = ap.Acquire_Load();
636c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org      }
637c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org      count++;
638d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      thread->stats.FinishedSingleOp();
639c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org    }
640c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org    if (ptr == NULL) exit(1); // Disable unused variable warning.
641c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org  }
642c6ac22e779e5135e494ddeb1d8e2b6008e9b619edgrogan@chromium.org
643d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  void SnappyCompress(ThreadState* thread) {
644d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    RandomGenerator gen;
645d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    Slice input = gen.Generate(Options().block_size);
64695e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    int64_t bytes = 0;
64795e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    int64_t produced = 0;
64895e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    bool ok = true;
64995e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    std::string compressed;
65095e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    while (ok && bytes < 1024 * 1048576) {  // Compress 1G
65195e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org      ok = port::Snappy_Compress(input.data(), input.size(), &compressed);
65295e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org      produced += compressed.size();
65395e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org      bytes += input.size();
654d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      thread->stats.FinishedSingleOp();
65595e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    }
65695e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org
65795e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    if (!ok) {
658d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      thread->stats.AddMessage("(snappy failure)");
65995e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    } else {
66095e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org      char buf[100];
66195e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org      snprintf(buf, sizeof(buf), "(output: %.1f%%)",
66295e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org               (produced * 100.0) / bytes);
663d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      thread->stats.AddMessage(buf);
664d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      thread->stats.AddBytes(bytes);
66595e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    }
66695e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org  }
66795e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org
668d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  void SnappyUncompress(ThreadState* thread) {
669d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    RandomGenerator gen;
670d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    Slice input = gen.Generate(Options().block_size);
67195e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    std::string compressed;
67295e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    bool ok = port::Snappy_Compress(input.data(), input.size(), &compressed);
67395e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    int64_t bytes = 0;
674f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com    char* uncompressed = new char[input.size()];
67595e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    while (ok && bytes < 1024 * 1048576) {  // Compress 1G
67695e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org      ok =  port::Snappy_Uncompress(compressed.data(), compressed.size(),
677f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com                                    uncompressed);
678f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com      bytes += input.size();
679d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      thread->stats.FinishedSingleOp();
68095e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    }
681f65a55c8d0744b95be29a65d06b59b22b012f37bgabor@google.com    delete[] uncompressed;
68295e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org
68395e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    if (!ok) {
684d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      thread->stats.AddMessage("(snappy failure)");
68595e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    } else {
686d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      thread->stats.AddBytes(bytes);
68795e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    }
68895e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org  }
68995e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org
690b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  void Open() {
691b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    assert(db_ == NULL);
692b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    Options options;
693a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    options.create_if_missing = !FLAGS_use_existing_db;
694b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    options.block_cache = cache_;
695b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    options.write_buffer_size = FLAGS_write_buffer_size;
69629c68f16466b1704dc7a663cf51bf9c5579830c3dgrogan@chromium.org    options.max_open_files = FLAGS_open_files;
69799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    options.filter_policy = filter_policy_;
6988cd4ab8303620197cf24282ae8639060efbb326egabor@google.com    Status s = DB::Open(options, FLAGS_db, &db_);
699b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    if (!s.ok()) {
700b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      fprintf(stderr, "open error: %s\n", s.ToString().c_str());
701b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      exit(1);
702b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    }
703b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  }
704b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org
705d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  void WriteSeq(ThreadState* thread) {
706d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    DoWrite(thread, true);
707d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  }
708b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org
709d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  void WriteRandom(ThreadState* thread) {
710d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    DoWrite(thread, false);
711d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  }
712d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com
713d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  void DoWrite(ThreadState* thread, bool seq) {
714d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    if (num_ != FLAGS_num) {
715b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      char msg[100];
716d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      snprintf(msg, sizeof(msg), "(%d ops)", num_);
717d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      thread->stats.AddMessage(msg);
718b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    }
719b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org
720d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    RandomGenerator gen;
721179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    WriteBatch batch;
722179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    Status s;
723d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    int64_t bytes = 0;
724d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    for (int i = 0; i < num_; i += entries_per_batch_) {
725179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      batch.Clear();
726d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      for (int j = 0; j < entries_per_batch_; j++) {
727d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        const int k = seq ? i+j : (thread->rand.Next() % FLAGS_num);
72895e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org        char key[100];
72995e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org        snprintf(key, sizeof(key), "%016d", k);
730d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        batch.Put(key, gen.Generate(value_size_));
731d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        bytes += value_size_ + strlen(key);
732d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com        thread->stats.FinishedSingleOp();
73395e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org      }
734d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      s = db_->Write(write_options_, &batch);
735179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      if (!s.ok()) {
736179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        fprintf(stderr, "put error: %s\n", s.ToString().c_str());
737179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org        exit(1);
738179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      }
739179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
740d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    thread->stats.AddBytes(bytes);
741179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
742179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
743d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  void ReadSequential(ThreadState* thread) {
744b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    Iterator* iter = db_->NewIterator(ReadOptions());
745b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    int i = 0;
746d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    int64_t bytes = 0;
747a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    for (iter->SeekToFirst(); i < reads_ && iter->Valid(); iter->Next()) {
748d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      bytes += iter->key().size() + iter->value().size();
749d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      thread->stats.FinishedSingleOp();
750b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      ++i;
751b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    }
752b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    delete iter;
753d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    thread->stats.AddBytes(bytes);
754b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  }
755b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org
756d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  void ReadReverse(ThreadState* thread) {
757b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    Iterator* iter = db_->NewIterator(ReadOptions());
758b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    int i = 0;
759d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    int64_t bytes = 0;
760a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    for (iter->SeekToLast(); i < reads_ && iter->Valid(); iter->Prev()) {
761d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      bytes += iter->key().size() + iter->value().size();
762d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      thread->stats.FinishedSingleOp();
763b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      ++i;
764b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    }
765b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    delete iter;
766d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    thread->stats.AddBytes(bytes);
767b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org  }
768b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org
769d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  void ReadRandom(ThreadState* thread) {
770179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    ReadOptions options;
771b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org    std::string value;
77299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    int found = 0;
773a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    for (int i = 0; i < reads_; i++) {
774b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      char key[100];
775d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      const int k = thread->rand.Next() % FLAGS_num;
776b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      snprintf(key, sizeof(key), "%016d", k);
77799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      if (db_->Get(options, key, &value).ok()) {
77899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        found++;
77999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      }
78099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      thread->stats.FinishedSingleOp();
78199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    }
78299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    char msg[100];
78399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    snprintf(msg, sizeof(msg), "(%d of %d found)", found, num_);
78499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    thread->stats.AddMessage(msg);
78599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  }
78699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
78799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  void ReadMissing(ThreadState* thread) {
78899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ReadOptions options;
78999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    std::string value;
79099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    for (int i = 0; i < reads_; i++) {
79199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      char key[100];
79299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      const int k = thread->rand.Next() % FLAGS_num;
79399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      snprintf(key, sizeof(key), "%016d.", k);
794b887f640bae906abfb77fdf418be63350b4c5e1fjorlow@chromium.org      db_->Get(options, key, &value);
795d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      thread->stats.FinishedSingleOp();
796179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
797179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
798179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
799d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  void ReadHot(ThreadState* thread) {
800a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    ReadOptions options;
801a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    std::string value;
802a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    const int range = (FLAGS_num + 99) / 100;
803a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    for (int i = 0; i < reads_; i++) {
804a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org      char key[100];
805d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      const int k = thread->rand.Next() % range;
806a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org      snprintf(key, sizeof(key), "%016d", k);
807a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org      db_->Get(options, key, &value);
808d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      thread->stats.FinishedSingleOp();
809a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    }
810a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  }
811a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org
81299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  void SeekRandom(ThreadState* thread) {
81399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    ReadOptions options;
81499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    std::string value;
81599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    int found = 0;
81699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    for (int i = 0; i < reads_; i++) {
81799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      Iterator* iter = db_->NewIterator(options);
81899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      char key[100];
81999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      const int k = thread->rand.Next() % FLAGS_num;
82099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      snprintf(key, sizeof(key), "%016d", k);
82199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      iter->Seek(key);
82299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      if (iter->Valid() && iter->key() == key) found++;
82399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      delete iter;
82499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      thread->stats.FinishedSingleOp();
82599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    }
82699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    char msg[100];
82799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    snprintf(msg, sizeof(msg), "(%d of %d found)", found, num_);
82899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    thread->stats.AddMessage(msg);
82999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  }
83099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
83199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  void DoDelete(ThreadState* thread, bool seq) {
83299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    RandomGenerator gen;
83399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    WriteBatch batch;
83499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    Status s;
83599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    for (int i = 0; i < num_; i += entries_per_batch_) {
83699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      batch.Clear();
83799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      for (int j = 0; j < entries_per_batch_; j++) {
83899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        const int k = seq ? i+j : (thread->rand.Next() % FLAGS_num);
83999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        char key[100];
84099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        snprintf(key, sizeof(key), "%016d", k);
84199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        batch.Delete(key);
84299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        thread->stats.FinishedSingleOp();
84399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      }
84499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      s = db_->Write(write_options_, &batch);
84599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      if (!s.ok()) {
84699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        fprintf(stderr, "del error: %s\n", s.ToString().c_str());
84799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com        exit(1);
84899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      }
84999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    }
85099a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  }
85199a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
85299a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  void DeleteSeq(ThreadState* thread) {
85399a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    DoDelete(thread, true);
85499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  }
85599a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
85699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  void DeleteRandom(ThreadState* thread) {
85799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    DoDelete(thread, false);
85899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  }
85999a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com
860394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com  void ReadWhileWriting(ThreadState* thread) {
861394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com    if (thread->tid > 0) {
862394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com      ReadRandom(thread);
863394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com    } else {
864394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com      // Special thread that keeps writing until other threads are done.
865394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com      RandomGenerator gen;
866394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com      while (true) {
867394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com        {
868394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com          MutexLock l(&thread->shared->mu);
869394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com          if (thread->shared->num_done + 1 >= thread->shared->num_initialized) {
870394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com            // Other threads have finished
871394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com            break;
872394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com          }
873394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com        }
874394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com
875394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com        const int k = thread->rand.Next() % FLAGS_num;
876394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com        char key[100];
877394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com        snprintf(key, sizeof(key), "%016d", k);
878394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com        Status s = db_->Put(write_options_, key, gen.Generate(value_size_));
879394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com        if (!s.ok()) {
880394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com          fprintf(stderr, "put error: %s\n", s.ToString().c_str());
881394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com          exit(1);
882394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com        }
883394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com      }
884394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com
885394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com      // Do not count any of the preceding work/delay in stats.
886394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com      thread->stats.Start();
887394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com    }
888394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com  }
889394a4b425a6a8aca3244fc26ec77c101a11a632cgabor@google.com
890d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com  void Compact(ThreadState* thread) {
8915fb21ed7ac9e91010d473ac77e132ae68f348d6agabor@google.com    db_->CompactRange(NULL, NULL);
892179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
893179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
89499a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com  void PrintStats(const char* key) {
89595e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    std::string stats;
89699a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    if (!db_->GetProperty(key, &stats)) {
897d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      stats = "(failed)";
89895e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    }
899d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    fprintf(stdout, "\n%s\n", stats.c_str());
90095e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org  }
90195e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org
902179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  static void WriteToFile(void* arg, const char* buf, int n) {
903179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    reinterpret_cast<WritableFile*>(arg)->Append(Slice(buf, n));
904179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
905179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
906179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  void HeapProfile() {
907179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    char fname[100];
9088cd4ab8303620197cf24282ae8639060efbb326egabor@google.com    snprintf(fname, sizeof(fname), "%s/heap-%04d", FLAGS_db, ++heap_counter_);
909179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    WritableFile* file;
910179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    Status s = Env::Default()->NewWritableFile(fname, &file);
911179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    if (!s.ok()) {
912d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      fprintf(stderr, "%s\n", s.ToString().c_str());
913179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      return;
914179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
915179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    bool ok = port::GetHeapProfile(WriteToFile, file);
916179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    delete file;
917179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    if (!ok) {
918d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      fprintf(stderr, "heap profiling not supported\n");
919179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      Env::Default()->DeleteFile(fname);
920179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
921179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
922179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org};
923179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
92445b9940be332834440bd5299419f396e38085ebehans@chromium.org}  // namespace leveldb
925179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
926179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.orgint main(int argc, char** argv) {
92795e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org  FLAGS_write_buffer_size = leveldb::Options().write_buffer_size;
928a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org  FLAGS_open_files = leveldb::Options().max_open_files;
929158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com  std::string default_db_path;
930a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org
931179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  for (int i = 1; i < argc; i++) {
932179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    double d;
933179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    int n;
934179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    char junk;
935179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    if (leveldb::Slice(argv[i]).starts_with("--benchmarks=")) {
936179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      FLAGS_benchmarks = argv[i] + strlen("--benchmarks=");
937179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    } else if (sscanf(argv[i], "--compression_ratio=%lf%c", &d, &junk) == 1) {
938179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      FLAGS_compression_ratio = d;
939179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    } else if (sscanf(argv[i], "--histogram=%d%c", &n, &junk) == 1 &&
940179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org               (n == 0 || n == 1)) {
941179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      FLAGS_histogram = n;
942a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    } else if (sscanf(argv[i], "--use_existing_db=%d%c", &n, &junk) == 1 &&
943a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org               (n == 0 || n == 1)) {
944a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org      FLAGS_use_existing_db = n;
945179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    } else if (sscanf(argv[i], "--num=%d%c", &n, &junk) == 1) {
946179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      FLAGS_num = n;
947a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    } else if (sscanf(argv[i], "--reads=%d%c", &n, &junk) == 1) {
948a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org      FLAGS_reads = n;
949d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com    } else if (sscanf(argv[i], "--threads=%d%c", &n, &junk) == 1) {
950d36ce84e66c7d3cee978fbeb52721c30dfb842a5gabor@google.com      FLAGS_threads = n;
951179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    } else if (sscanf(argv[i], "--value_size=%d%c", &n, &junk) == 1) {
952179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      FLAGS_value_size = n;
953179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    } else if (sscanf(argv[i], "--write_buffer_size=%d%c", &n, &junk) == 1) {
954179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      FLAGS_write_buffer_size = n;
95595e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    } else if (sscanf(argv[i], "--cache_size=%d%c", &n, &junk) == 1) {
95695e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org      FLAGS_cache_size = n;
95799a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com    } else if (sscanf(argv[i], "--bloom_bits=%d%c", &n, &junk) == 1) {
95899a7585544fc162a5f8dd39a6add00776a981efesanjay@google.com      FLAGS_bloom_bits = n;
959a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org    } else if (sscanf(argv[i], "--open_files=%d%c", &n, &junk) == 1) {
960a5b4129c0a8c01158cde2244a5811f15b9d45ec0dgrogan@chromium.org      FLAGS_open_files = n;
9618cd4ab8303620197cf24282ae8639060efbb326egabor@google.com    } else if (strncmp(argv[i], "--db=", 5) == 0) {
9628cd4ab8303620197cf24282ae8639060efbb326egabor@google.com      FLAGS_db = argv[i] + 5;
96395e21f32367748825123e382172ecbfd492ddb23dgrogan@chromium.org    } else {
964179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      fprintf(stderr, "Invalid flag '%s'\n", argv[i]);
965179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org      exit(1);
966179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org    }
967179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  }
968179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org
969158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com  // Choose a location for the test database if none given with --db=<path>
970158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com  if (FLAGS_db == NULL) {
971158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com      leveldb::Env::Default()->GetTestDirectory(&default_db_path);
972158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com      default_db_path += "/dbbench";
973158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com      FLAGS_db = default_db_path.c_str();
974158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com  }
975158f767acaed4c39cbb3ee8128fe896e155ec40csanjay@google.com
976179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  leveldb::Benchmark benchmark;
977179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  benchmark.Run();
978179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org  return 0;
979179be588c25dccaa963df9c9c104fc6229435483jorlow@chromium.org}
980