DEFINE_double(compression_ratio, 0.5, "Arrange to generate values that shrink"
" to this fraction of their original size after compression");
+DEFINE_double(
+ overwrite_probability, 0.0,
+ "Used in 'filluniquerandom' benchmark: for each write operation, "
+ "we give a probability to perform an overwrite instead. The key used for "
+ "the overwrite is randomly chosen from the last 'overwrite_window_size' "
+ "keys "
+ "previously inserted into the DB. "
+ "Valid overwrite_probability values: [0.0, 1.0].");
+
+DEFINE_uint32(overwrite_window_size, 1,
+ "Used in 'filluniquerandom' benchmark. For each write "
+ "operation, when "
+ "the overwrite_probability flag is set by the user, the key used "
+ "to perform "
+ "an overwrite is randomly chosen from the last "
+ "'overwrite_window_size' keys "
+ "previously inserted into the DB. "
+ "Warning: large values can affect throughput. "
+ "Valid overwrite_window_size values: [1, kMaxUint32].");
+
DEFINE_double(read_random_exp_range, 0.0,
"Read random's key will be generated using distribution of "
"num * exp(-r) where r is uniform number from 0 to this value. "
Slice begin_key = AllocateKey(&begin_key_guard);
std::unique_ptr<const char[]> end_key_guard;
Slice end_key = AllocateKey(&end_key_guard);
+ double p = 0.0;
+ uint64_t num_overwrites = 0, num_unique_keys = 0;
+ // If user set overwrite_probability flag,
+ // check if value is in [0.0,1.0].
+ if (FLAGS_overwrite_probability > 0.0) {
+ p = FLAGS_overwrite_probability > 1.0 ? 1.0 : FLAGS_overwrite_probability;
+ // If overwrite set by user, and UNIQUE_RANDOM mode on,
+ // the overwrite_window_size must be > 0.
+ if (write_mode == UNIQUE_RANDOM && FLAGS_overwrite_window_size == 0) {
+ fprintf(stderr,
+ "Overwrite_window_size must be strictly greater than 0.\n");
+ ErrorExit();
+ }
+ }
+
+ // Default_random_engine provides slightly
+ // improved throughput over mt19937.
+ std::default_random_engine overwrite_gen{
+ static_cast<unsigned int>(FLAGS_seed)};
+ std::bernoulli_distribution overwrite_decider(p);
+
+ // Inserted key window is filled with the last N
+ // keys previously inserted into the DB (with
+ // N=FLAGS_overwrite_window_size).
+ // We use a deque struct because:
+ // - random access is O(1)
+ // - insertion/removal at beginning/end is also O(1).
+ std::deque<int64_t> inserted_key_window;
+ Random64 reservoir_id_gen(FLAGS_seed);
+
std::vector<std::unique_ptr<const char[]>> expanded_key_guards;
std::vector<Slice> expanded_keys;
if (FLAGS_expand_range_tombstones) {
int64_t batch_bytes = 0;
for (int64_t j = 0; j < entries_per_batch_; j++) {
- int64_t rand_num = key_gens[id]->Next();
+ int64_t rand_num = 0;
+ if ((write_mode == UNIQUE_RANDOM) && (p > 0.0)) {
+ if ((inserted_key_window.size() > 0) &&
+ overwrite_decider(overwrite_gen)) {
+ num_overwrites++;
+ rand_num = inserted_key_window[reservoir_id_gen.Next() %
+ inserted_key_window.size()];
+ } else {
+ num_unique_keys++;
+ rand_num = key_gens[id]->Next();
+ if (inserted_key_window.size() < FLAGS_overwrite_window_size) {
+ inserted_key_window.push_back(rand_num);
+ } else {
+ inserted_key_window.pop_front();
+ inserted_key_window.push_back(rand_num);
+ }
+ }
+ } else {
+ rand_num = key_gens[id]->Next();
+ }
GenerateKeyFromInt(rand_num, FLAGS_num, &key);
Slice val = gen.Generate();
if (use_blob_db_) {
ErrorExit();
}
}
+ if ((write_mode == UNIQUE_RANDOM) && (p > 0.0)) {
+ fprintf(stdout,
+ "Number of unique keys inerted: %" PRIu64
+ ".\nNumber of overwrites: %" PRIu64 "\n",
+ num_unique_keys, num_overwrites);
+ }
thread->stats.AddBytes(bytes);
}