mirror of https://github.com/facebook/rocksdb.git
Phase 1 of an iterator stress test
Summary: Added MultiIterate() which does a seek and some Next/Prev calls. Iterator status is checked only, no data integrity check Test Plan: make db_stress ./db_stress --iterpercent=<nonzero value> --readpercent=, etc. Reviewers: emayanke, dhruba, xjin Reviewed By: emayanke CC: leveldb Differential Revision: https://reviews.facebook.net/D12915
This commit is contained in:
parent
4734dbb742
commit
433541823c
|
@ -183,14 +183,20 @@ static int FLAGS_level0_slowdown_writes_trigger = 8;
|
||||||
static unsigned int FLAGS_readpercent = 10;
|
static unsigned int FLAGS_readpercent = 10;
|
||||||
|
|
||||||
// Ratio of prefix iterators to total workload (expressed as a percentage)
|
// Ratio of prefix iterators to total workload (expressed as a percentage)
|
||||||
static unsigned int FLAGS_prefixpercent = 25;
|
static unsigned int FLAGS_prefixpercent = 20;
|
||||||
|
|
||||||
// Ratio of deletes to total workload (expressed as a percentage)
|
// Ratio of deletes to total workload (expressed as a percentage)
|
||||||
static unsigned int FLAGS_writepercent = 50;
|
static unsigned int FLAGS_writepercent = 45;
|
||||||
|
|
||||||
// Ratio of deletes to total workload (expressed as a percentage)
|
// Ratio of deletes to total workload (expressed as a percentage)
|
||||||
static unsigned int FLAGS_delpercent = 15;
|
static unsigned int FLAGS_delpercent = 15;
|
||||||
|
|
||||||
|
// Ratio of iterations to total workload (expressed as a percentage)
|
||||||
|
static unsigned int FLAGS_iterpercent = 10;
|
||||||
|
|
||||||
|
// Number of iterations per MultiIterate run
|
||||||
|
static uint32_t FLAGS_num_iterations = 10;
|
||||||
|
|
||||||
// Option to disable compation triggered by read.
|
// Option to disable compation triggered by read.
|
||||||
static int FLAGS_disable_seek_compaction = false;
|
static int FLAGS_disable_seek_compaction = false;
|
||||||
|
|
||||||
|
@ -266,6 +272,7 @@ class Stats {
|
||||||
long deletes_;
|
long deletes_;
|
||||||
long iterator_size_sums_;
|
long iterator_size_sums_;
|
||||||
long founds_;
|
long founds_;
|
||||||
|
long iterations_;
|
||||||
long errors_;
|
long errors_;
|
||||||
int next_report_;
|
int next_report_;
|
||||||
size_t bytes_;
|
size_t bytes_;
|
||||||
|
@ -285,6 +292,7 @@ class Stats {
|
||||||
deletes_ = 0;
|
deletes_ = 0;
|
||||||
iterator_size_sums_ = 0;
|
iterator_size_sums_ = 0;
|
||||||
founds_ = 0;
|
founds_ = 0;
|
||||||
|
iterations_ = 0;
|
||||||
errors_ = 0;
|
errors_ = 0;
|
||||||
bytes_ = 0;
|
bytes_ = 0;
|
||||||
seconds_ = 0;
|
seconds_ = 0;
|
||||||
|
@ -302,6 +310,7 @@ class Stats {
|
||||||
deletes_ += other.deletes_;
|
deletes_ += other.deletes_;
|
||||||
iterator_size_sums_ += other.iterator_size_sums_;
|
iterator_size_sums_ += other.iterator_size_sums_;
|
||||||
founds_ += other.founds_;
|
founds_ += other.founds_;
|
||||||
|
iterations_ += other.iterations_;
|
||||||
errors_ += other.errors_;
|
errors_ += other.errors_;
|
||||||
bytes_ += other.bytes_;
|
bytes_ += other.bytes_;
|
||||||
seconds_ += other.seconds_;
|
seconds_ += other.seconds_;
|
||||||
|
@ -353,6 +362,10 @@ class Stats {
|
||||||
iterator_size_sums_ += count;
|
iterator_size_sums_ += count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AddIterations(int n) {
|
||||||
|
iterations_ += n;
|
||||||
|
}
|
||||||
|
|
||||||
void AddDeletes(int n) {
|
void AddDeletes(int n) {
|
||||||
deletes_ += n;
|
deletes_ += n;
|
||||||
}
|
}
|
||||||
|
@ -385,6 +398,7 @@ class Stats {
|
||||||
fprintf(stdout, "%-12s: Prefix scanned %ld times\n", "", prefixes_);
|
fprintf(stdout, "%-12s: Prefix scanned %ld times\n", "", prefixes_);
|
||||||
fprintf(stdout, "%-12s: Iterator size sum is %ld\n", "",
|
fprintf(stdout, "%-12s: Iterator size sum is %ld\n", "",
|
||||||
iterator_size_sums_);
|
iterator_size_sums_);
|
||||||
|
fprintf(stdout, "%-12s: Iterated %ld times\n", "", iterations_);
|
||||||
fprintf(stdout, "%-12s: Got errors %ld times\n", "", errors_);
|
fprintf(stdout, "%-12s: Got errors %ld times\n", "", errors_);
|
||||||
|
|
||||||
if (FLAGS_histogram) {
|
if (FLAGS_histogram) {
|
||||||
|
@ -891,6 +905,37 @@ class StressTest {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Given a key K, this creates an iterator which scans to K and then
|
||||||
|
// does a random sequence of Next/Prev operations.
|
||||||
|
Status MultiIterate(ThreadState* thread,
|
||||||
|
const ReadOptions& readoptions,
|
||||||
|
const Slice& key) {
|
||||||
|
Status s;
|
||||||
|
const Snapshot* snapshot = db_->GetSnapshot();
|
||||||
|
ReadOptions readoptionscopy = readoptions;
|
||||||
|
readoptionscopy.snapshot = snapshot;
|
||||||
|
unique_ptr<Iterator> iter(db_->NewIterator(readoptionscopy));
|
||||||
|
|
||||||
|
iter->Seek(key);
|
||||||
|
for (long i = 0; i < FLAGS_num_iterations && iter->Valid(); i++) {
|
||||||
|
if (thread->rand.OneIn(2)) {
|
||||||
|
iter->Next();
|
||||||
|
} else {
|
||||||
|
iter->Prev();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s.ok()) {
|
||||||
|
thread->stats.AddIterations(1);
|
||||||
|
} else {
|
||||||
|
thread->stats.AddErrors(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
db_->ReleaseSnapshot(snapshot);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
void OperateDb(ThreadState* thread) {
|
void OperateDb(ThreadState* thread) {
|
||||||
ReadOptions read_opts(FLAGS_verify_checksum, true);
|
ReadOptions read_opts(FLAGS_verify_checksum, true);
|
||||||
WriteOptions write_opts;
|
WriteOptions write_opts;
|
||||||
|
@ -901,6 +946,9 @@ class StressTest {
|
||||||
write_opts.sync = true;
|
write_opts.sync = true;
|
||||||
}
|
}
|
||||||
write_opts.disableWAL = FLAGS_disable_wal;
|
write_opts.disableWAL = FLAGS_disable_wal;
|
||||||
|
const int prefixBound = (int)FLAGS_readpercent + (int)FLAGS_prefixpercent;
|
||||||
|
const int writeBound = prefixBound + (int)FLAGS_writepercent;
|
||||||
|
const int delBound = writeBound + (int)FLAGS_delpercent;
|
||||||
|
|
||||||
thread->stats.Start();
|
thread->stats.Start();
|
||||||
for (long i = 0; i < FLAGS_ops_per_thread; i++) {
|
for (long i = 0; i < FLAGS_ops_per_thread; i++) {
|
||||||
|
@ -926,8 +974,8 @@ class StressTest {
|
||||||
Slice key = keystr;
|
Slice key = keystr;
|
||||||
int prob_op = thread->rand.Uniform(100);
|
int prob_op = thread->rand.Uniform(100);
|
||||||
|
|
||||||
// OPERATION read?
|
|
||||||
if (prob_op >= 0 && prob_op < (int)FLAGS_readpercent) {
|
if (prob_op >= 0 && prob_op < (int)FLAGS_readpercent) {
|
||||||
|
// OPERATION read
|
||||||
if (!FLAGS_test_batches_snapshots) {
|
if (!FLAGS_test_batches_snapshots) {
|
||||||
Status s = db_->Get(read_opts, key, &from_db);
|
Status s = db_->Get(read_opts, key, &from_db);
|
||||||
if (s.ok()) {
|
if (s.ok()) {
|
||||||
|
@ -943,11 +991,8 @@ class StressTest {
|
||||||
} else {
|
} else {
|
||||||
MultiGet(thread, read_opts, key, &from_db);
|
MultiGet(thread, read_opts, key, &from_db);
|
||||||
}
|
}
|
||||||
}
|
} else if ((int)FLAGS_readpercent <= prob_op && prob_op < prefixBound) {
|
||||||
prob_op -= FLAGS_readpercent;
|
// OPERATION prefix scan
|
||||||
|
|
||||||
// OPERATION prefix scan?
|
|
||||||
if (prob_op >= 0 && prob_op < (int)FLAGS_prefixpercent) {
|
|
||||||
// keys are longs (e.g., 8 bytes), so we let prefixes be
|
// keys are longs (e.g., 8 bytes), so we let prefixes be
|
||||||
// everything except the last byte. So there will be 2^8=256
|
// everything except the last byte. So there will be 2^8=256
|
||||||
// keys per prefix.
|
// keys per prefix.
|
||||||
|
@ -970,11 +1015,8 @@ class StressTest {
|
||||||
} else {
|
} else {
|
||||||
MultiPrefixScan(thread, read_opts, prefix);
|
MultiPrefixScan(thread, read_opts, prefix);
|
||||||
}
|
}
|
||||||
}
|
} else if (prefixBound <= prob_op && prob_op < writeBound) {
|
||||||
prob_op -= FLAGS_prefixpercent;
|
// OPERATION write
|
||||||
|
|
||||||
// OPERATION write?
|
|
||||||
if (prob_op >= 0 && prob_op < (int)FLAGS_writepercent) {
|
|
||||||
uint32_t value_base = thread->rand.Next();
|
uint32_t value_base = thread->rand.Next();
|
||||||
size_t sz = GenerateValue(value_base, value, sizeof(value));
|
size_t sz = GenerateValue(value_base, value, sizeof(value));
|
||||||
Slice v(value, sz);
|
Slice v(value, sz);
|
||||||
|
@ -994,11 +1036,8 @@ class StressTest {
|
||||||
MultiPut(thread, write_opts, key, v, sz);
|
MultiPut(thread, write_opts, key, v, sz);
|
||||||
}
|
}
|
||||||
PrintKeyValue(rand_key, value, sz);
|
PrintKeyValue(rand_key, value, sz);
|
||||||
}
|
} else if (writeBound <= prob_op && prob_op < delBound) {
|
||||||
prob_op -= FLAGS_writepercent;
|
// OPERATION delete
|
||||||
|
|
||||||
// OPERATION delete?
|
|
||||||
if (prob_op >= 0 && prob_op < (int)FLAGS_delpercent) {
|
|
||||||
if (!FLAGS_test_batches_snapshots) {
|
if (!FLAGS_test_batches_snapshots) {
|
||||||
MutexLock l(thread->shared->GetMutexForKey(rand_key));
|
MutexLock l(thread->shared->GetMutexForKey(rand_key));
|
||||||
thread->shared->Delete(rand_key);
|
thread->shared->Delete(rand_key);
|
||||||
|
@ -1007,11 +1046,13 @@ class StressTest {
|
||||||
} else {
|
} else {
|
||||||
MultiDelete(thread, write_opts, key);
|
MultiDelete(thread, write_opts, key);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// OPERATION iterate
|
||||||
|
MultiIterate(thread, read_opts, key);
|
||||||
}
|
}
|
||||||
prob_op -= FLAGS_delpercent;
|
|
||||||
|
|
||||||
thread->stats.FinishedSingleOp();
|
thread->stats.FinishedSingleOp();
|
||||||
}
|
}
|
||||||
|
|
||||||
thread->stats.Stop();
|
thread->stats.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1096,8 +1137,9 @@ class StressTest {
|
||||||
fprintf(stdout, "Prefix percentage : %d\n", FLAGS_prefixpercent);
|
fprintf(stdout, "Prefix percentage : %d\n", FLAGS_prefixpercent);
|
||||||
fprintf(stdout, "Write percentage : %d\n", FLAGS_writepercent);
|
fprintf(stdout, "Write percentage : %d\n", FLAGS_writepercent);
|
||||||
fprintf(stdout, "Delete percentage : %d\n", FLAGS_delpercent);
|
fprintf(stdout, "Delete percentage : %d\n", FLAGS_delpercent);
|
||||||
|
fprintf(stdout, "Iterate percentage : %d\n", FLAGS_iterpercent);
|
||||||
fprintf(stdout, "Write-buffer-size : %d\n", FLAGS_write_buffer_size);
|
fprintf(stdout, "Write-buffer-size : %d\n", FLAGS_write_buffer_size);
|
||||||
fprintf(stdout, "Delete percentage : %d\n", FLAGS_delpercent);
|
fprintf(stdout, "Iterations : %d\n", FLAGS_num_iterations);
|
||||||
fprintf(stdout, "Max key : %ld\n", FLAGS_max_key);
|
fprintf(stdout, "Max key : %ld\n", FLAGS_max_key);
|
||||||
fprintf(stdout, "Ratio #ops/#keys : %f\n",
|
fprintf(stdout, "Ratio #ops/#keys : %f\n",
|
||||||
(1.0 * FLAGS_ops_per_thread * FLAGS_threads)/FLAGS_max_key);
|
(1.0 * FLAGS_ops_per_thread * FLAGS_threads)/FLAGS_max_key);
|
||||||
|
@ -1391,9 +1433,14 @@ int main(int argc, char** argv) {
|
||||||
} else if (sscanf(argv[i], "--writepercent=%d%c", &n, &junk) == 1 &&
|
} else if (sscanf(argv[i], "--writepercent=%d%c", &n, &junk) == 1 &&
|
||||||
(n >= 0 && n <= 100)) {
|
(n >= 0 && n <= 100)) {
|
||||||
FLAGS_writepercent = n;
|
FLAGS_writepercent = n;
|
||||||
|
} else if (sscanf(argv[i], "--iterpercent=%d%c", &n, &junk) == 1 &&
|
||||||
|
(n >= 0 && n <= 100)) {
|
||||||
|
FLAGS_iterpercent = n;
|
||||||
} else if (sscanf(argv[i], "--delpercent=%d%c", &n, &junk) == 1 &&
|
} else if (sscanf(argv[i], "--delpercent=%d%c", &n, &junk) == 1 &&
|
||||||
(n >= 0 && n <= 100)) {
|
(n >= 0 && n <= 100)) {
|
||||||
FLAGS_delpercent = n;
|
FLAGS_delpercent = n;
|
||||||
|
} else if (sscanf(argv[i], "--numiterations=%u%c", &u, &junk) == 1) {
|
||||||
|
FLAGS_num_iterations = u;
|
||||||
} else if (sscanf(argv[i], "--disable_data_sync=%d%c", &n, &junk) == 1 &&
|
} else if (sscanf(argv[i], "--disable_data_sync=%d%c", &n, &junk) == 1 &&
|
||||||
(n == 0 || n == 1)) {
|
(n == 0 || n == 1)) {
|
||||||
FLAGS_disable_data_sync = n;
|
FLAGS_disable_data_sync = n;
|
||||||
|
@ -1497,8 +1544,9 @@ int main(int argc, char** argv) {
|
||||||
FLAGS_env->SetBackgroundThreads(FLAGS_max_background_compactions);
|
FLAGS_env->SetBackgroundThreads(FLAGS_max_background_compactions);
|
||||||
|
|
||||||
if ((FLAGS_readpercent + FLAGS_prefixpercent +
|
if ((FLAGS_readpercent + FLAGS_prefixpercent +
|
||||||
FLAGS_writepercent + FLAGS_delpercent) != 100) {
|
FLAGS_writepercent + FLAGS_delpercent + FLAGS_iterpercent) != 100) {
|
||||||
fprintf(stderr, "Error: Read+Prefix+Write+Delete percents != 100!\n");
|
fprintf(stderr,
|
||||||
|
"Error: Read+Prefix+Write+Delete+Iterate percents != 100!\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (FLAGS_disable_wal == 1 && FLAGS_reopen > 0) {
|
if (FLAGS_disable_wal == 1 && FLAGS_reopen > 0) {
|
||||||
|
|
Loading…
Reference in New Issue