[PATCH] backend: compare word-at-a-time in bcTruelen - Mailing list pgsql-hackers

From Jeremy Kerr
Subject [PATCH] backend: compare word-at-a-time in bcTruelen
Date
Msg-id 1245805503.62025.32374376046.1.gpush@pingu
Whole thread Raw
In response to Re: [PATCH] backend: compare word-at-a-time in bcTruelen  (Jeremy Kerr <jk@ozlabs.org>)
Responses Re: [PATCH] backend: compare word-at-a-time in bcTruelen  (Robert Haas <robertmhaas@gmail.com>)
List pgsql-hackers
The current bcTruelen function uses a simple reverse array scan to
find the legth of a space-padded string. On some workloads (it shows
in sysbench), this can result in a lot of time spent in this function.

This change introduces a word-at-a-time comparison in bcTruelen, aiming
to reduce the number of compares where possible. Word-size compares
are performed on aligned sections of the string.

Results in a small performance increase; around 1-2% on my POWER6 test
box.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>

---
Resend: context diff this time

---src/backend/utils/adt/varchar.c |   24 +++++++++++++++++++++---1 file changed, 21 insertions(+), 3 deletions(-)

*** a/src/backend/utils/adt/varchar.c
--- b/src/backend/utils/adt/varchar.c
***************
*** 624,639 **** varchartypmodout(PG_FUNCTION_ARGS) static int bcTruelen(BpChar *arg) {     char       *s =
VARDATA_ANY(arg);    int            i;
 
-     int            len; 
!     len = VARSIZE_ANY_EXHDR(arg);
!     for (i = len - 1; i >= 0; i--)     {         if (s[i] != ' ')             break;     }     return i + 1; } 
--- 624,657 ---- static int bcTruelen(BpChar *arg) {
+     const uint32_t    spaces = 0x20202020;
+     const int    wordsize = sizeof(spaces);     char       *s = VARDATA_ANY(arg);     int            i; 
!     i = VARSIZE_ANY_EXHDR(arg) - 1;
! 
!     /* compare down to an aligned boundary */
!     for (; i > 0 && !PointerIsAligned(s + i - (wordsize - 1), uint32_t); i--)     {         if (s[i] != ' ')
+             return i + 1;
+     }
+ 
+     /* now that we're aligned, compare word at a time */
+     for (; i >= wordsize - 1; i -= wordsize)
+     {
+         if (*(uint32_t *)(s + i - (wordsize - 1)) != spaces)             break;     }
+ 
+     /* check within the last non-matching word */
+     for (; i >= 0; i--)
+     {
+         if (s[i] != ' ')
+             break;
+     }
+      return i + 1; } 


pgsql-hackers by date:

Previous
From: Peter Eisentraut
Date:
Subject: that picksplit debug message again
Next
From: Robert Haas
Date:
Subject: Re: [PATCH] backend: compare word-at-a-time in bcTruelen