aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Mohr <andi@lisas.de>2006-03-28 08:59:49 +0200
committerJens Axboe <axboe@suse.de>2006-03-28 08:59:49 +0200
commite8a99053ea82a4b4375049886cf1db64d7dcd755 (patch)
treef16f440237e5627bda317923198fbbe00cb22e96
parent[PATCH] [BLOCK] cfq-iosched: change cfq io context linking from list to tree (diff)
downloadlinux-dev-e8a99053ea82a4b4375049886cf1db64d7dcd755.tar.xz
linux-dev-e8a99053ea82a4b4375049886cf1db64d7dcd755.zip
[PATCH] cfq-iosched: small cfq_choose_req() optimization
this is a small optimization to cfq_choose_req() in the CFQ I/O scheduler (this function is a semi-often invoked candidate in an oprofile log): by using a bit mask variable, we can use a simple switch() to check the various cases instead of having to query two variables for each check. Benefit: 251 vs. 285 bytes footprint of cfq_choose_req(). Also, common case 0 (no request wrapping) is now checked first in code. Signed-off-by: Andreas Mohr <andi@lisas.de> Signed-off-by: Jens Axboe <axboe@suse.de>
-rw-r--r--block/cfq-iosched.c50
1 files changed, 32 insertions, 18 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index bb43a1677626..15152e2da0d2 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -346,14 +346,16 @@ static int cfq_queue_empty(request_queue_t *q)
/*
* Lifted from AS - choose which of crq1 and crq2 that is best served now.
* We choose the request that is closest to the head right now. Distance
- * behind the head are penalized and only allowed to a certain extent.
+ * behind the head is penalized and only allowed to a certain extent.
*/
static struct cfq_rq *
cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2)
{
sector_t last, s1, s2, d1 = 0, d2 = 0;
- int r1_wrap = 0, r2_wrap = 0; /* requests are behind the disk head */
unsigned long back_max;
+#define CFQ_RQ1_WRAP 0x01 /* request 1 wraps */
+#define CFQ_RQ2_WRAP 0x02 /* request 2 wraps */
+ unsigned wrap = 0; /* bit mask: requests behind the disk head? */
if (crq1 == NULL || crq1 == crq2)
return crq2;
@@ -385,35 +387,47 @@ cfq_choose_req(struct cfq_data *cfqd, struct cfq_rq *crq1, struct cfq_rq *crq2)
else if (s1 + back_max >= last)
d1 = (last - s1) * cfqd->cfq_back_penalty;
else
- r1_wrap = 1;
+ wrap |= CFQ_RQ1_WRAP;
if (s2 >= last)
d2 = s2 - last;
else if (s2 + back_max >= last)
d2 = (last - s2) * cfqd->cfq_back_penalty;
else
- r2_wrap = 1;
+ wrap |= CFQ_RQ2_WRAP;
/* Found required data */
- if (!r1_wrap && r2_wrap)
- return crq1;
- else if (!r2_wrap && r1_wrap)
- return crq2;
- else if (r1_wrap && r2_wrap) {
- /* both behind the head */
- if (s1 <= s2)
+
+ /*
+ * By doing switch() on the bit mask "wrap" we avoid having to
+ * check two variables for all permutations: --> faster!
+ */
+ switch (wrap) {
+ case 0: /* common case for CFQ: crq1 and crq2 not wrapped */
+ if (d1 < d2)
return crq1;
- else
+ else if (d2 < d1)
return crq2;
- }
+ else {
+ if (s1 >= s2)
+ return crq1;
+ else
+ return crq2;
+ }
- /* Both requests in front of the head */
- if (d1 < d2)
+ case CFQ_RQ2_WRAP:
return crq1;
- else if (d2 < d1)
+ case CFQ_RQ1_WRAP:
return crq2;
- else {
- if (s1 >= s2)
+ case (CFQ_RQ1_WRAP|CFQ_RQ2_WRAP): /* both crqs wrapped */
+ default:
+ /*
+ * Since both rqs are wrapped,
+ * start with the one that's further behind head
+ * (--> only *one* back seek required),
+ * since back seek takes more time than forward.
+ */
+ if (s1 <= s2)
return crq1;
else
return crq2;