[io_generator] Support mixed sequential and random io pattern

This commit is contained in:
Ming-Hung Tsai 2020-07-23 23:58:15 +08:00
parent 7ed013fcab
commit 061d966e7a
3 changed files with 88 additions and 11 deletions

View File

@ -44,25 +44,45 @@ namespace {
: begin_(begin), : begin_(begin),
end_(begin + (size / step) * step), end_(begin + (size / step) * step),
step_(step), step_(step),
current_(begin) { current_(begin),
rounds_(0) {
if (size < step) if (size < step)
throw std::runtime_error("size must be greater than the step"); throw std::runtime_error("size must be greater than the step");
} }
forward_sequence_generator()
: begin_(0), end_(1), step_(1),
current_(0), rounds_(0) {
}
uint64_t next() { uint64_t next() {
uint64_t r = current_; uint64_t r = current_;
current_ += step_; current_ += step_;
if (current_ >= end_) { if (current_ >= end_) {
current_ = begin_; current_ = begin_;
++rounds_;
} }
return r; return r;
} }
void reset(uint64_t begin, uint64_t size, uint64_t step = 1) {
begin_ = begin;
end_ = begin + (size / step) * step;
step_ = step;
current_ = begin;
rounds_ = 0;
}
uint64_t get_rounds() {
return rounds_;
}
private: private:
uint64_t begin_; uint64_t begin_;
uint64_t end_; uint64_t end_;
uint64_t step_; uint64_t step_;
uint64_t current_; uint64_t current_;
uint64_t rounds_;
}; };
// - The maximum generated value is not greater than (begin+size) // - The maximum generated value is not greater than (begin+size)
@ -73,21 +93,25 @@ namespace {
// TODO: load random seeds // TODO: load random seeds
random_sequence_generator(uint64_t begin, random_sequence_generator(uint64_t begin,
uint64_t size, uint64_t size,
uint64_t step) uint64_t step,
unsigned seq_nr = 1)
: begin_(begin), : begin_(begin),
nr_steps_(size / step), nr_steps_(size / step),
step_(step), step_(step),
nr_generated_(0) { max_forward_steps_(seq_nr),
nr_generated_(0)
{
if (!max_forward_steps_ || max_forward_steps_ > nr_steps_)
throw std::runtime_error("invalid number of forward steps");
if (max_forward_steps_ > 1)
reset_forward_generator();
} }
uint64_t next() { uint64_t next() {
uint64_t step_idx; // FIXME: eliminate if-else
uint64_t step_idx = (max_forward_steps_ > 1) ?
bool found = true; next_forward_step() : next_random_step();
while (found) {
step_idx = std::rand() % nr_steps_;
found = rand_map_.member(step_idx);
}
rand_map_.add(step_idx); rand_map_.add(step_idx);
++nr_generated_; ++nr_generated_;
@ -101,12 +125,47 @@ namespace {
} }
private: private:
void reset_forward_generator() {
uint64_t begin = next_random_step();
unsigned seq_nr = (std::rand() % max_forward_steps_) + 1;
forward_gen_.reset(begin, seq_nr);
}
uint64_t next_forward_step() {
uint64_t step_idx;
bool found = true;
while (found) {
step_idx = forward_gen_.next();
found = rand_map_.member(step_idx);
if (found || forward_gen_.get_rounds())
reset_forward_generator();
}
return step_idx;
}
uint64_t next_random_step() const {
uint64_t step_idx;
bool found = true;
while (found) {
step_idx = std::rand() % nr_steps_;
found = rand_map_.member(step_idx);
}
return step_idx;
}
uint64_t begin_; uint64_t begin_;
uint64_t nr_steps_; uint64_t nr_steps_;
uint64_t step_; uint64_t step_;
unsigned max_forward_steps_;
base::run_set<uint64_t> rand_map_; base::run_set<uint64_t> rand_map_;
uint64_t nr_generated_; uint64_t nr_generated_;
forward_sequence_generator forward_gen_;
}; };
//-------------------------------- //--------------------------------
@ -187,7 +246,8 @@ namespace {
if (opts.pattern_.is_random()) if (opts.pattern_.is_random())
gen = new random_sequence_generator(opts.offset_, gen = new random_sequence_generator(opts.offset_,
opts.size_, opts.block_size_); opts.size_, opts.block_size_,
opts.nr_seq_blocks_);
else else
gen = new forward_sequence_generator(opts.offset_, gen = new forward_sequence_generator(opts.offset_,
opts.size_, opts.block_size_); opts.size_, opts.block_size_);

View File

@ -36,6 +36,7 @@ namespace base {
sector_t block_size_; sector_t block_size_;
sector_t size_; sector_t size_;
sector_t io_size_; sector_t io_size_;
unsigned nr_seq_blocks_;
}; };
class io_generator { class io_generator {

View File

@ -47,6 +47,7 @@ namespace {
base::sector_t offset; base::sector_t offset;
boost::optional<base::sector_t> size; boost::optional<base::sector_t> size;
boost::optional<base::sector_t> io_size; boost::optional<base::sector_t> io_size;
boost::optional<unsigned> nr_seq_blocks;
}; };
bool flags::check_conformance() { bool flags::check_conformance() {
@ -65,6 +66,14 @@ namespace {
return false; return false;
} }
if (nr_seq_blocks) {
if (!pattern.is_random()) {
cerr << "Cannot specify the sequence size"
" while doing non-random IO" << endl;
return false;
}
}
check_output_file_requirements(*output); check_output_file_requirements(*output);
return true; return true;
@ -90,6 +99,7 @@ namespace {
opts.offset_ = fs.offset; opts.offset_ = fs.offset;
opts.size_ = *fs.size; opts.size_ = *fs.size;
opts.io_size_ = !fs.io_size ? *fs.size : *fs.io_size; opts.io_size_ = !fs.io_size ? *fs.size : *fs.io_size;
opts.nr_seq_blocks_ = !fs.nr_seq_blocks ? 1 : *fs.nr_seq_blocks;
io_generator::ptr gen = create_io_generator(opts); io_generator::ptr gen = create_io_generator(opts);
base::io io; base::io io;
@ -133,6 +143,7 @@ thin_generate_mappings_cmd::usage(std::ostream &out) const
<< " {--io-size} <io-size in sectors>\n" << " {--io-size} <io-size in sectors>\n"
<< " {--rw write|trim|randwrite|randtrim|randtw}\n" << " {--rw write|trim|randwrite|randtrim|randtw}\n"
<< " {--size} <size in sectors>\n" << " {--size} <size in sectors>\n"
<< " {--seq-nr} <max nr. of sequential ios>\n"
<< " {-V|--version}" << endl; << " {-V|--version}" << endl;
} }
@ -150,6 +161,7 @@ thin_generate_mappings_cmd::run(int argc, char **argv)
{ "offset", required_argument, NULL, 3 }, { "offset", required_argument, NULL, 3 },
{ "size", required_argument, NULL, 4 }, { "size", required_argument, NULL, 4 },
{ "io-size", required_argument, NULL, 5 }, { "io-size", required_argument, NULL, 5 },
{ "seq-nr", required_argument, NULL, 6 },
{ "version", no_argument, NULL, 'V' }, { "version", no_argument, NULL, 'V' },
{ NULL, no_argument, NULL, 0 } { NULL, no_argument, NULL, 0 }
}; };
@ -184,6 +196,10 @@ thin_generate_mappings_cmd::run(int argc, char **argv)
fs.io_size = parse_uint64(optarg, "io_size"); fs.io_size = parse_uint64(optarg, "io_size");
break; break;
case 6:
fs.nr_seq_blocks = parse_uint64(optarg, "seq_nr");
break;
case 'V': case 'V':
cout << THIN_PROVISIONING_TOOLS_VERSION << endl; cout << THIN_PROVISIONING_TOOLS_VERSION << endl;
return 0; return 0;