summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2023-08-28 00:15:34 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-08-28 00:15:34 -0400
commit4d1d83b5980e1270b08849839f167412dfc73a6e (patch)
tree8ed20fb14ef78862509bb56d0fa33716d96a9030
parent63747ac6534e3092f703527ba809eb93034bd57b (diff)
start for new benchmark codebenchmark
-rw-r--r--tools-util.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/tools-util.c b/tools-util.c
index 81ce63ae..0f2df4e7 100644
--- a/tools-util.c
+++ b/tools-util.c
@@ -678,3 +678,115 @@ struct bbpos bbpos_parse(char *buf)
ret.pos = bpos_parse(s);
return ret;
}
+
+enum benchmark_mode {
+ BENCHMARK_SEQREAD,
+ BENCHMARK_SEQWRITE,
+ BENCHMARK_RANDREAD,
+ BENCHMARK_RANDWRITE,
+};
+
+struct benchmark_bio {
+ unsigned idx;
+ bool complete;
+ void *p;
+ struct bio bio;
+ struct bio_vec bv;
+};
+
+struct benchmark_bios {
+ struct block_device *bdev;
+ enum benchmark_mode mode;
+ unsigned blocksize;
+ u64 nr_done;
+ wait_queue_head_t wait;
+ struct benchmark_bio bios[64];
+};
+
+static void benchmark_device_endio(struct bio *bio)
+{
+ struct benchmark_bio *bbio = container_of(bio, struct benchmark_bio, bio);
+ struct benchmark_bios *bios = container_of(bbio, struct benchmark_bios, bios[bbio->idx]);
+
+ bbio->complete = true;
+
+ wake_up(&bios->wait);
+}
+
+static bool benchmark_submit(struct benchmark_bios *bios)
+{
+ bool submitted = false;
+
+ for (unsigned i = 0; i < ARRAY_SIZE(bios->bios); i++) {
+ struct bio *bio = &bios->bios[i].bio;
+
+ if (!bios->bios[i].complete)
+ continue;
+
+ bios->bios[i].complete = false;
+ bio_init(&bios->bios[i].bio, bios->bdev, &bios->bios[i].bv, 1, 0);
+ bio->bi_end_io = benchmark_device_endio;
+
+ bch2_bio_map(bio, bios->bios[i].p, bios->blocksize << 9);
+
+ switch (bios->mode) {
+ case BENCHMARK_SEQREAD:
+ bio->bi_opf = REQ_OP_READ;
+ bio->bi_iter.bi_sector = bios->nr_done * bios->blocksize;
+ break;
+ case BENCHMARK_SEQWRITE:
+ bio->bi_opf = REQ_OP_WRITE;
+ bio->bi_iter.bi_sector = bios->nr_done * bios->blocksize;
+ break;
+ case BENCHMARK_RANDREAD:
+ bio->bi_opf = REQ_OP_READ;
+ bio->bi_iter.bi_sector = // get random number
+ break;
+ case BENCHMARK_RANDWRITE:
+ bio->bi_opf = REQ_OP_WRITE;
+ bio->bi_iter.bi_sector = // get random number * bios->blocksize
+ break;
+ }
+
+ submit_bio(bio);
+
+ submitted = true;
+ bios->nr_done++;
+ }
+
+ return submitted;
+}
+
+int benchmark_device(struct block_device *bdev, enum benchmark_mode mode)
+{
+ struct benchmark_bios bios;
+ unsigned i;
+
+ bios.bdev = bdev;
+ bios.mode = mode;
+ bios.nr_done = 0;
+ init_waitqueue_head(&bios.wait);
+
+ for (i = 0; i < ARRAY_SIZE(bios.bios); i++) {
+ bios.bios[i].idx = i;
+ bios.bios[i].complete = true;
+ bios.bios[i].p = kmalloc(bios.blocksize << 9, GFP_KERNEL);
+ }
+
+ struct timespec start_ts, now_ts;
+ clock_gettime(CLOCK_MONOTONIC, &start_ts);
+
+ u64 start = timespec_to_ns(&start_ts);
+
+ while (true) {
+ wait_event(bios.wait, benchmark_submit(&bios));
+
+ clock_gettime(CLOCK_MONOTONIC, &now_ts);
+ u64 now = timespec_to_ns(&now_ts);
+
+ if (start - now > 5 * NSEC_PER_SEC)
+ break;
+ }
+
+ return bios.nr_done / 5;
+}