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; }