From: "Yu, Zhang" <yu.c.zhang@linux.intel.com>
To: Paul Durrant <Paul.Durrant@citrix.com>,
"xen-devel@lists.xen.org" <xen-devel@lists.xen.org>,
Ian Jackson <Ian.Jackson@citrix.com>,
Stefano Stabellini <Stefano.Stabellini@citrix.com>,
Ian Campbell <Ian.Campbell@citrix.com>,
Wei Liu <wei.liu2@citrix.com>, "Keir (Xen.org)" <keir@xen.org>,
"jbeulich@suse.com" <jbeulich@suse.com>,
Andrew Cooper <Andrew.Cooper3@citrix.com>
Cc: Kevin Tian <kevin.tian@intel.com>,
"zhiyuan.lv@intel.com" <zhiyuan.lv@intel.com>
Subject: Re: [PATCH v4 2/2] Refactor rangeset structure for better performance.
Date: Thu, 13 Aug 2015 18:46:30 +0800 [thread overview]
Message-ID: <55CC7586.1070609@linux.intel.com> (raw)
In-Reply-To: <9AAE0902D5BC7E449B7C8E4E778ABCD02F581452@AMSPEX01CL01.citrite.net>
On 8/13/2015 6:33 PM, Paul Durrant wrote:
>> -----Original Message-----
>> From: Yu Zhang [mailto:yu.c.zhang@linux.intel.com]
>> Sent: 13 August 2015 11:06
>> To: xen-devel@lists.xen.org; Paul Durrant; Ian Jackson; Stefano Stabellini; Ian
>> Campbell; Wei Liu; Keir (Xen.org); jbeulich@suse.com; Andrew Cooper
>> Cc: Kevin Tian; zhiyuan.lv@intel.com
>> Subject: [PATCH v4 2/2] Refactor rangeset structure for better performance.
>>
>> This patch refactors struct rangeset to base it on the red-black
>> tree structure, instead of on the current doubly linked list. By
>> now, ioreq leverages rangeset to keep track of the IO/memory
>> resources to be emulated. Yet when number of ranges inside one
>> ioreq server is very high, traversing a doubly linked list could
>> be time consuming. With this patch, the time complexity for
>> searching a rangeset can be improved from O(n) to O(log(n)).
>> Interfaces of rangeset still remain the same, and no new APIs
>> introduced.
>>
>> Signed-off-by: Yu Zhang <yu.c.zhang@linux.intel.com>
>> ---
>> xen/common/rangeset.c | 82
>> +++++++++++++++++++++++++++++++++++++--------------
>> 1 file changed, 60 insertions(+), 22 deletions(-)
>>
>> diff --git a/xen/common/rangeset.c b/xen/common/rangeset.c
>> index 6c6293c..87b6aab 100644
>> --- a/xen/common/rangeset.c
>> +++ b/xen/common/rangeset.c
>> @@ -10,11 +10,12 @@
>> #include <xen/sched.h>
>> #include <xen/errno.h>
>> #include <xen/rangeset.h>
>> +#include <xen/rbtree.h>
>> #include <xsm/xsm.h>
>>
>> /* An inclusive range [s,e] and pointer to next range in ascending order. */
>> struct range {
>> - struct list_head list;
>> + struct rb_node node;
>> unsigned long s, e;
>> };
>>
>> @@ -24,7 +25,7 @@ struct rangeset {
>> struct domain *domain;
>>
>> /* Ordered list of ranges contained in this set, and protecting lock. */
>> - struct list_head range_list;
>> + struct rb_root range_tree;
>>
>> /* Number of ranges that can be allocated */
>> long nr_ranges;
>> @@ -45,41 +46,78 @@ struct rangeset {
>> static struct range *find_range(
>> struct rangeset *r, unsigned long s)
>> {
>> - struct range *x = NULL, *y;
>> + struct rb_node *node;
>> + struct range *x;
>> + struct range *prev = NULL;
>>
>> - list_for_each_entry ( y, &r->range_list, list )
>> + node = r->range_tree.rb_node;
>> + while ( node )
>> {
>> - if ( y->s > s )
>> - break;
>> - x = y;
>> + x = container_of(node, struct range, node);
>> + if ( (s >= x->s) && (s <= x->e) )
>> + return x;
>> + if ( s < x->s )
>> + node = node->rb_left;
>> + else if ( s > x->s )
>
> Do you need else if there? I think else would do. s either has to be < x->s or > x->e to get to this point.
Thanks. You are right. :)
>
>> + {
>> + prev = x;
>> + node = node->rb_right;
>> + }
>> }
>>
>> - return x;
>> + return prev;
>
> Do you not want to return NULL here? It looks like you'd only get here if there was no matching range.
Well, prev can either be NULL(like its initial value), or pointing to
the previous node of the range. It's to keep the original intention of
routine find_range() - to return the range if found, or return the
previous one, or NULL.
B.R.
Yu
>
> Paul
>
>> }
>>
>> /* Return the lowest range in the set r, or NULL if r is empty. */
>> static struct range *first_range(
>> struct rangeset *r)
>> {
>> - if ( list_empty(&r->range_list) )
>> - return NULL;
>> - return list_entry(r->range_list.next, struct range, list);
>> + struct rb_node *node;
>> +
>> + node = rb_first(&r->range_tree);
>> + if ( node != NULL )
>> + return container_of(node, struct range, node);
>> +
>> + return NULL;
>> }
>>
>> /* Return range following x in ascending order, or NULL if x is the highest. */
>> static struct range *next_range(
>> struct rangeset *r, struct range *x)
>> {
>> - if ( x->list.next == &r->range_list )
>> - return NULL;
>> - return list_entry(x->list.next, struct range, list);
>> + struct rb_node *node;
>> +
>> + node = rb_next(&x->node);
>> + if ( node )
>> + return container_of(node, struct range, node);
>> +
>> + return NULL;
>> }
>>
>> /* Insert range y after range x in r. Insert as first range if x is NULL. */
>> static void insert_range(
>> struct rangeset *r, struct range *x, struct range *y)
>> {
>> - list_add(&y->list, (x != NULL) ? &x->list : &r->range_list);
>> + struct rb_node **node;
>> + struct rb_node *parent = NULL;
>> +
>> + if ( x == NULL )
>> + node = &r->range_tree.rb_node;
>> + else
>> + {
>> + node = &x->node.rb_right;
>> + parent = &x->node;
>> + }
>> +
>> + while ( *node )
>> + {
>> + parent = *node;
>> + node = &parent->rb_left;
>> + }
>> +
>> + /* Add new node and rebalance the red-black tree. */
>> + rb_link_node(&y->node, parent, node);
>> + rb_insert_color(&y->node, &r->range_tree);
>> }
>>
>> /* Remove a range from its list and free it. */
>> @@ -88,7 +126,7 @@ static void destroy_range(
>> {
>> r->nr_ranges++;
>>
>> - list_del(&x->list);
>> + rb_erase(&x->node, &r->range_tree);
>> xfree(x);
>> }
>>
>> @@ -319,7 +357,7 @@ bool_t rangeset_contains_singleton(
>> bool_t rangeset_is_empty(
>> const struct rangeset *r)
>> {
>> - return ((r == NULL) || list_empty(&r->range_list));
>> + return ((r == NULL) || RB_EMPTY_ROOT(&r->range_tree));
>> }
>>
>> struct rangeset *rangeset_new(
>> @@ -332,7 +370,7 @@ struct rangeset *rangeset_new(
>> return NULL;
>>
>> rwlock_init(&r->lock);
>> - INIT_LIST_HEAD(&r->range_list);
>> + r->range_tree = RB_ROOT;
>> r->nr_ranges = -1;
>>
>> BUG_ON(flags & ~RANGESETF_prettyprint_hex);
>> @@ -410,7 +448,7 @@ void rangeset_domain_destroy(
>>
>> void rangeset_swap(struct rangeset *a, struct rangeset *b)
>> {
>> - LIST_HEAD(tmp);
>> + struct rb_node* tmp;
>>
>> if ( a < b )
>> {
>> @@ -423,9 +461,9 @@ void rangeset_swap(struct rangeset *a, struct
>> rangeset *b)
>> write_lock(&a->lock);
>> }
>>
>> - list_splice_init(&a->range_list, &tmp);
>> - list_splice_init(&b->range_list, &a->range_list);
>> - list_splice(&tmp, &b->range_list);
>> + tmp = a->range_tree.rb_node;
>> + a->range_tree.rb_node = b->range_tree.rb_node;
>> + b->range_tree.rb_node = tmp;
>>
>> write_unlock(&a->lock);
>> write_unlock(&b->lock);
>> --
>> 1.9.1
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel
>
>
next prev parent reply other threads:[~2015-08-13 10:46 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-08-13 10:05 [PATCH v4 0/2] Refactor ioreq server for better performance Yu Zhang
2015-08-13 10:05 ` [PATCH v4 1/2] Differentiate IO/mem resources tracked by ioreq server Yu Zhang
2015-08-13 10:16 ` Paul Durrant
2015-08-13 10:39 ` Yu, Zhang
2015-08-14 7:40 ` Yu, Zhang
2015-08-14 8:46 ` Paul Durrant
2015-08-14 9:30 ` Yu, Zhang
2015-08-13 10:05 ` [PATCH v4 2/2] Refactor rangeset structure for better performance Yu Zhang
2015-08-13 10:33 ` Paul Durrant
2015-08-13 10:46 ` Yu, Zhang [this message]
2015-08-13 11:29 ` Paul Durrant
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=55CC7586.1070609@linux.intel.com \
--to=yu.c.zhang@linux.intel.com \
--cc=Andrew.Cooper3@citrix.com \
--cc=Ian.Campbell@citrix.com \
--cc=Ian.Jackson@citrix.com \
--cc=Paul.Durrant@citrix.com \
--cc=Stefano.Stabellini@citrix.com \
--cc=jbeulich@suse.com \
--cc=keir@xen.org \
--cc=kevin.tian@intel.com \
--cc=wei.liu2@citrix.com \
--cc=xen-devel@lists.xen.org \
--cc=zhiyuan.lv@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.