From: Daniel Santos <danielfsantos@att.net>
To: Peter Zijlstra <peterz@infradead.org>
Cc: linux-kernel@vger.kernel.org
Subject: Generic rbtree: compare() vs less()
Date: Sun, 03 Jun 2012 18:16:18 -0500 [thread overview]
Message-ID: <4FCBF042.2090208@att.net> (raw)
Peter,
I wanted to get with you on something you mentioned in IRC, as well as
one of your emails. The (primary) reason my code uses a compare()
function instead of less() is that it has to work with trees that allow
unique keys. In the fair scheduler, it doesn't matter because:
a.) duplicate keys are allowed
b.) you never need to do lookups.
If you had to do lookups, you would have to call less() twice:
if (less(p->key, key)) {
p = p->right;
} else if (less(key, p->key)) {
p = p->right;
} else {
return p;
}
Using compare() means that you only call this function once and allows
for the possibility that some trees might have a more complication
compare function. Plus, on gcc 4.5 and earlier, it's not inlining the
compare function call. :(
The reason I'm returning long from compare() instead of returning int,
is to hopefully simplify the generated code for compare functions that
need to subtract two 64-bit values and still not incur additional
overhead. If I used int, then the compare function for a 64-bit value
would have to look like this:
int compare(u64 *a, u64 *b) {
return *a > *b ? 1 : (*a < *b ? -1 : 0);
}
// or
int compare(u64 *a, u64 *b) {
s64 diff = *a - *b;
return diff > 0 ? 1: (diff < 0 ? -1 : 0);
}
And that's a whole lot more instructions, unless the compiler can inline
the function, compared the two values, use the CPU's negative & zero
flags and just completely compiled out int return value which, sadly,
just doesn't seem to happen very often. :( (especially on 4.5 and
earlier where it fails to inline the compare function call).
Incidentally, this is what I've done on my fair.c patch:
+static inline long compare_vruntime(u64 *a, u64 *b)
+{
+#if __BITS_PER_LONG >= 64
+ return (long)((s64)*a - (s64)*b);
+#else
+/* This is hacky, but is done to reduce instructions -- we wont use
this for
+ * rbtree lookups, only inserts, and since our relationship is defined as
+ * non-unique, we only need to return positive if a > b and any other value
+ * means less than.
+ */
+ return (long)(*a > *b);
+#endif
+}
This should keep the instruction count pretty much what it was prior to
my patch on 32-bit systems as well as 64.
Anyway, please let me know if you have any other ideas on this! I'm
going to write up a Q&A or something that explains the reasons for some
of these seemingly odd decisions. (maybe I'll even find some better
alternatives after getting feedback)
Daniel
reply other threads:[~2012-06-03 23:16 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=4FCBF042.2090208@att.net \
--to=danielfsantos@att.net \
--cc=daniel.santos@pobox.com \
--cc=linux-kernel@vger.kernel.org \
--cc=peterz@infradead.org \
/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.