Avoid using the rbtree if we don't have to
authorJens Axboe <jens.axboe@oracle.com>
Tue, 27 Mar 2007 08:36:12 +0000 (10:36 +0200)
committerJens Axboe <jens.axboe@oracle.com>
Tue, 27 Mar 2007 08:36:12 +0000 (10:36 +0200)
Basically reinstate the old logic of not sorting when it's
not a win for reading the data back.

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
fio.c
fio.h
log.c
verify.c

diff --git a/fio.c b/fio.c
index 6a3a87b0feb9257c5e38b3f7826fc2ba96d08d31..bed1e28770d1b2cb2a79edf0dccfd9bc796a28e4 100644 (file)
--- a/fio.c
+++ b/fio.c
@@ -736,6 +736,7 @@ static void *thread_main(void *data)
        INIT_LIST_HEAD(&td->io_u_busylist);
        INIT_LIST_HEAD(&td->io_u_requeues);
        INIT_LIST_HEAD(&td->io_log_list);
        INIT_LIST_HEAD(&td->io_u_busylist);
        INIT_LIST_HEAD(&td->io_u_requeues);
        INIT_LIST_HEAD(&td->io_log_list);
+       INIT_LIST_HEAD(&td->io_hist_list);
        td->io_hist_tree = RB_ROOT;
 
        if (init_io_u(td))
        td->io_hist_tree = RB_ROOT;
 
        if (init_io_u(td))
diff --git a/fio.h b/fio.h
index 4d7e6ea7d8410132e787e577631c44a24b1b440d..ec08e42350f47b5428e8f166205b1fc680d7155f 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -515,9 +515,15 @@ struct thread_data {
        unsigned int ddir_nr;
 
        /*
        unsigned int ddir_nr;
 
        /*
-        * IO historic logs
+        * IO history logs for verification. We use a tree for sorting,
+        * if we are overwriting. Otherwise just use a fifo.
         */
        struct rb_root io_hist_tree;
         */
        struct rb_root io_hist_tree;
+       struct list_head io_hist_list;
+
+       /*
+        * For IO replaying
+        */
        struct list_head io_log_list;
 
        /*
        struct list_head io_log_list;
 
        /*
diff --git a/log.c b/log.c
index 0614b277c1e9de3752b977c284aa2531f9581049..6c7c4d6b2680546663eeac7d179b2e11917b7997 100644 (file)
--- a/log.c
+++ b/log.c
@@ -43,16 +43,33 @@ void prune_io_piece_log(struct thread_data *td)
  */
 void log_io_piece(struct thread_data *td, struct io_u *io_u)
 {
  */
 void log_io_piece(struct thread_data *td, struct io_u *io_u)
 {
-       struct rb_node **p = &td->io_hist_tree.rb_node;
-       struct rb_node *parent = NULL;
+       struct rb_node **p, *parent;
        struct io_piece *ipo, *__ipo;
 
        ipo = malloc(sizeof(struct io_piece));
        struct io_piece *ipo, *__ipo;
 
        ipo = malloc(sizeof(struct io_piece));
-       RB_CLEAR_NODE(&ipo->rb_node);
        ipo->file = io_u->file;
        ipo->offset = io_u->offset;
        ipo->len = io_u->buflen;
 
        ipo->file = io_u->file;
        ipo->offset = io_u->offset;
        ipo->len = io_u->buflen;
 
+       /*
+        * We don't need to sort the entries, if:
+        *
+        *      Sequential writes, or
+        *      Random writes that lay out the file as it goes along
+        *
+        * For both these cases, just reading back data in the order we
+        * wrote it out is the fastest.
+        */
+       if (!td_random(td) || !td->o.overwrite) {
+               INIT_LIST_HEAD(&ipo->list);
+               list_add_tail(&ipo->list, &td->io_hist_list);
+               return;
+       }
+
+       RB_CLEAR_NODE(&ipo->rb_node);
+       p = &td->io_hist_tree.rb_node;
+       parent = NULL;
+
        /*
         * Sort the entry into the verification list
         */
        /*
         * Sort the entry into the verification list
         */
index 99b21e8fd922e5f0d3124df5d9e6be7b7438d484..47335107452a13dee3cded9fc2fe5907e1d3cb14 100644 (file)
--- a/verify.c
+++ b/verify.c
@@ -150,8 +150,7 @@ void populate_verify_io_u(struct thread_data *td, struct io_u *io_u)
 
 int get_next_verify(struct thread_data *td, struct io_u *io_u)
 {
 
 int get_next_verify(struct thread_data *td, struct io_u *io_u)
 {
-       struct io_piece *ipo;
-       struct rb_node *n;
+       struct io_piece *ipo = NULL;
 
        /*
         * this io_u is from a requeue, we already filled the offsets
 
        /*
         * this io_u is from a requeue, we already filled the offsets
@@ -159,12 +158,17 @@ int get_next_verify(struct thread_data *td, struct io_u *io_u)
        if (io_u->file)
                return 0;
 
        if (io_u->file)
                return 0;
 
-       n = rb_first(&td->io_hist_tree);
-       if (n) {
-               ipo = rb_entry(n, struct io_piece, rb_node);
+       if (!RB_EMPTY_ROOT(&td->io_hist_tree)) {
+               struct rb_node *n = rb_first(&td->io_hist_tree);
 
 
+               ipo = rb_entry(n, struct io_piece, rb_node);
                rb_erase(n, &td->io_hist_tree);
                rb_erase(n, &td->io_hist_tree);
+       } else if (!list_empty(&td->io_hist_list)) {
+               ipo = list_entry(td->io_hist_list.next, struct io_piece, list);
+               list_del(&ipo->list);
+       }
 
 
+       if (ipo) {
                io_u->offset = ipo->offset;
                io_u->buflen = ipo->len;
                io_u->file = ipo->file;
                io_u->offset = ipo->offset;
                io_u->buflen = ipo->len;
                io_u->file = ipo->file;