tools/rados: Fix rand & seq read bench to use num ops instead of num objs when issuing and tracking outstanding IO

ObjBencher::seq_read_bench() is using "num_objects > data.started" to make sure
we don't issue more reads than what was written during ObjBencher::write_bench().
However, this does not work op_size != object_size as data.started is number of read
ops issued, not number of objects read.
This fix modifies ObjBencher::seq_read_bench() to use "num_ops > data.started" instead.
Where "num_ops" is metadata saved at the end of ObjBencher::write_bench().

ObjBencher::rand_read_bench() is using "rand() % num_objects" for rand_id and
"rand_id / reads_per_object" to generate object name.
This will not work correctly when reads_per_object != 1 (i.e. when op_size != object_size).
For example, if reads_per_object = 100 and num_objects = 2, then all generated
reads will be directed towards the first object, with no read for the second object.
This fix modifies ObjBencher::rand_read_bench() to use "rand() % num_ops" for rand_id instead.
Where "num_ops" is metadata saved at the end of ObjBencher::write_bench().

This patch also modifies ObjBencher::write_bench() to save number of write operations issued
(num_ops above), rather than number of objects written (num_objects). We can always derive
num_objects based on "(num_ops + ops_per_object - 1) / ops_per_object" where "ops_per_object"
is simply object_size / op_size.

Signed-off-by: Albert H Chen <hselin.chen@gmail.com>
This commit is contained in:
Albert H Chen 2019-09-15 19:40:55 +00:00
parent e487604ad2
commit c28a00cfa5
2 changed files with 29 additions and 19 deletions

42
src/common/obj_bencher.cc Normal file → Executable file
View File

@ -244,6 +244,7 @@ int ObjBencher::aio_bench(
if (concurrentios <= 0)
return -EINVAL;
int num_ops = 0;
int num_objects = 0;
int r = 0;
int prev_pid = 0;
@ -256,7 +257,7 @@ int ObjBencher::aio_bench(
if (operation != OP_WRITE || reuse_bench) {
uint64_t prev_op_size, prev_object_size;
r = fetch_bench_metadata(run_name_meta, &prev_op_size, &prev_object_size,
&num_objects, &prev_pid);
&num_ops, &num_objects, &prev_pid);
if (r < 0) {
if (r == -ENOENT) {
if (reuse_bench)
@ -297,17 +298,17 @@ int ObjBencher::aio_bench(
if (r != 0) goto out;
}
else if (OP_SEQ_READ == operation) {
r = seq_read_bench(secondsToRun, num_objects, concurrentios, prev_pid, no_verify);
r = seq_read_bench(secondsToRun, num_ops, num_objects, concurrentios, prev_pid, no_verify);
if (r != 0) goto out;
}
else if (OP_RAND_READ == operation) {
r = rand_read_bench(secondsToRun, num_objects, concurrentios, prev_pid, no_verify);
r = rand_read_bench(secondsToRun, num_ops, num_objects, concurrentios, prev_pid, no_verify);
if (r != 0) goto out;
}
if (OP_WRITE == operation && cleanup) {
r = fetch_bench_metadata(run_name_meta, &op_size, &object_size,
&num_objects, &prev_pid);
&num_ops, &num_objects, &prev_pid);
if (r < 0) {
if (r == -ENOENT)
cerr << "Should never happen: bench metadata missing for current run!" << std::endl;
@ -353,7 +354,7 @@ void _aio_cb(void *cb, void *arg) {
int ObjBencher::fetch_bench_metadata(const std::string& metadata_file,
uint64_t *op_size, uint64_t* object_size,
int* num_objects, int* prevPid) {
int* num_ops, int* num_objects, int* prevPid) {
int r = 0;
bufferlist object_data;
@ -368,13 +369,19 @@ int ObjBencher::fetch_bench_metadata(const std::string& metadata_file,
}
auto p = object_data.cbegin();
decode(*object_size, p);
decode(*num_objects, p);
decode(*num_ops, p);
decode(*prevPid, p);
if (!p.end()) {
decode(*op_size, p);
} else {
*op_size = *object_size;
}
unsigned ops_per_object = 1;
// make sure *op_size value is reasonable
if (*op_size > 0 && *object_size > *op_size) {
ops_per_object = *object_size / *op_size;
}
*num_objects = (*num_ops + ops_per_object - 1) / ops_per_object;
return 0;
}
@ -458,7 +465,6 @@ int ObjBencher::write_bench(int secondsToRun,
//keep on adding new writes as old ones complete until we've passed minimum time
int slot;
int num_objects;
//don't need locking for reads because other thread doesn't write
@ -627,8 +633,7 @@ int ObjBencher::write_bench(int secondsToRun,
}
//write object size/number data for read benchmarks
encode(data.object_size, b_write);
num_objects = (data.finished + writes_per_object - 1) / writes_per_object;
encode(num_objects, b_write);
encode(data.finished, b_write);
encode(prev_pid ? prev_pid : getpid(), b_write);
encode(data.op_size, b_write);
@ -647,7 +652,10 @@ int ObjBencher::write_bench(int secondsToRun,
return r;
}
int ObjBencher::seq_read_bench(int seconds_to_run, int num_objects, int concurrentios, int pid, bool no_verify) {
int ObjBencher::seq_read_bench(
int seconds_to_run, int num_ops, int num_objects,
int concurrentios, int pid, bool no_verify) {
lock_cond lc(&lock);
if (concurrentios <= 0)
@ -713,7 +721,7 @@ int ObjBencher::seq_read_bench(int seconds_to_run, int num_objects, int concurre
slot = 0;
while ((seconds_to_run && mono_clock::now() < finish_time) &&
num_objects > data.started) {
num_ops > data.started) {
locker.lock();
int old_slot = slot;
bool found = false;
@ -881,8 +889,10 @@ int ObjBencher::seq_read_bench(int seconds_to_run, int num_objects, int concurre
return r;
}
int ObjBencher::rand_read_bench(int seconds_to_run, int num_objects, int concurrentios, int pid, bool no_verify)
{
int ObjBencher::rand_read_bench(
int seconds_to_run, int num_ops, int num_objects,
int concurrentios, int pid, bool no_verify) {
lock_cond lc(&lock);
if (concurrentios <= 0)
@ -1006,7 +1016,7 @@ int ObjBencher::rand_read_bench(int seconds_to_run, int num_objects, int concurr
}
}
rand_id = rand() % num_objects;
rand_id = rand() % num_ops;
newName = generate_object_name_fast(rand_id / reads_per_object, pid);
index[slot] = rand_id;
release_completion(slot);
@ -1124,7 +1134,7 @@ int ObjBencher::rand_read_bench(int seconds_to_run, int num_objects, int concurr
int ObjBencher::clean_up(const std::string& orig_prefix, int concurrentios, const std::string& run_name) {
int r = 0;
uint64_t op_size, object_size;
int num_objects;
int num_ops, num_objects;
int prevPid;
// default meta object if user does not specify one
@ -1171,7 +1181,7 @@ int ObjBencher::clean_up(const std::string& orig_prefix, int concurrentios, cons
continue;
}
r = fetch_bench_metadata(run_name_meta, &op_size, &object_size, &num_objects, &prevPid);
r = fetch_bench_metadata(run_name_meta, &op_size, &object_size, &num_ops, &num_objects, &prevPid);
if (r < 0) {
return r;
}

View File

@ -75,11 +75,11 @@ protected:
struct bench_data data;
int fetch_bench_metadata(const std::string& metadata_file, uint64_t* op_size,
uint64_t* object_size, int* num_objects, int* prev_pid);
uint64_t* object_size, int* num_ops, int* num_objects, int* prev_pid);
int write_bench(int secondsToRun, int concurrentios, const string& run_name_meta, unsigned max_objects, int prev_pid);
int seq_read_bench(int secondsToRun, int num_objects, int concurrentios, int writePid, bool no_verify=false);
int rand_read_bench(int secondsToRun, int num_objects, int concurrentios, int writePid, bool no_verify=false);
int seq_read_bench(int secondsToRun, int num_ops, int num_objects, int concurrentios, int writePid, bool no_verify=false);
int rand_read_bench(int secondsToRun, int num_ops, int num_objects, int concurrentios, int writePid, bool no_verify=false);
int clean_up(int num_objects, int prevPid, int concurrentios);
bool more_objects_matching_prefix(const std::string& prefix, std::list<Object>* name);