From 33feb55c478af5f7a4c61232729c524d69d8d965 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 20 Jan 2006 22:46:16 +0000 Subject: [PATCH] Replace bitwise looping with bytewise looping in hemdistsign and sizebitvec of tsearch2, as well as identical code in several other contrib modules. This provided about a 20X speedup in building a large tsearch2 index ... didn't try to measure its effects for other operations. Thanks to Stephan Vollmer for providing a test case. --- contrib/intarray/_int.h | 5 ---- contrib/intarray/_intbig_gist.c | 39 ++++++++++++++++++------------ contrib/ltree/_ltree_gist.c | 42 +++++++++++++++++++++------------ contrib/ltree/ltree.h | 8 ------- contrib/pg_trgm/trgm.h | 5 ---- contrib/pg_trgm/trgm_gist.c | 39 ++++++++++++++++++------------ contrib/tsearch2/gistidx.c | 40 +++++++++++++++++++------------ contrib/tsearch2/gistidx.h | 4 ---- 8 files changed, 100 insertions(+), 82 deletions(-) diff --git a/contrib/intarray/_int.h b/contrib/intarray/_int.h index ec09b14973..af67435309 100644 --- a/contrib/intarray/_int.h +++ b/contrib/intarray/_int.h @@ -68,11 +68,6 @@ typedef char *BITVECP; a;\ } -#define LOOPBIT(a) \ - for(i=0;i> (i)) & 0x01 ) diff --git a/contrib/intarray/_intbig_gist.c b/contrib/intarray/_intbig_gist.c index 0064e450dd..844236068d 100644 --- a/contrib/intarray/_intbig_gist.c +++ b/contrib/intarray/_intbig_gist.c @@ -20,16 +20,25 @@ Datum g_intbig_picksplit(PG_FUNCTION_ARGS); Datum g_intbig_union(PG_FUNCTION_ARGS); Datum g_intbig_same(PG_FUNCTION_ARGS); -#define SUMBIT(val) ( \ - GETBITBYTE((val),0) + \ - GETBITBYTE((val),1) + \ - GETBITBYTE((val),2) + \ - GETBITBYTE((val),3) + \ - GETBITBYTE((val),4) + \ - GETBITBYTE((val),5) + \ - GETBITBYTE((val),6) + \ - GETBITBYTE((val),7) \ -) +/* Number of one-bits in an unsigned byte */ +static const uint8 number_of_ones[256] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 +}; PG_FUNCTION_INFO_V1(_intbig_in); Datum _intbig_in(PG_FUNCTION_ARGS); @@ -205,8 +214,7 @@ sizebitvec(BITVECP sign) i; LOOPBYTE( - size += SUMBIT(sign); - sign = (BITVECP) (((char *) sign) + 1); + size += number_of_ones[(unsigned char) sign[i]]; ); return size; } @@ -215,11 +223,12 @@ static int hemdistsign(BITVECP a, BITVECP b) { int i, + diff, dist = 0; - LOOPBIT( - if (GETBIT(a, i) != GETBIT(b, i)) - dist++; + LOOPBYTE( + diff = (unsigned char) (a[i] ^ b[i]); + dist += number_of_ones[diff]; ); return dist; } diff --git a/contrib/ltree/_ltree_gist.c b/contrib/ltree/_ltree_gist.c index 44e25fd28f..b95dc33334 100644 --- a/contrib/ltree/_ltree_gist.c +++ b/contrib/ltree/_ltree_gist.c @@ -30,18 +30,30 @@ Datum _ltree_consistent(PG_FUNCTION_ARGS); #define GETENTRY(vec,pos) ((ltree_gist *) DatumGetPointer((vec)->vector[(pos)].key)) #define NEXTVAL(x) ( (ltree*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) ) -#define SUMBIT(val) ( \ - GETBITBYTE(val,0) + \ - GETBITBYTE(val,1) + \ - GETBITBYTE(val,2) + \ - GETBITBYTE(val,3) + \ - GETBITBYTE(val,4) + \ - GETBITBYTE(val,5) + \ - GETBITBYTE(val,6) + \ - GETBITBYTE(val,7) \ -) + +/* Number of one-bits in an unsigned byte */ +static const uint8 number_of_ones[256] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 +}; + #define WISH_F(a,b,c) (double)( -(double)(((a)-(b))*((a)-(b))*((a)-(b)))*(c) ) + static void hashing(BITVECP sign, ltree * t) { @@ -207,8 +219,7 @@ sizebitvec(BITVECP sign) i; ALOOPBYTE( - size += SUMBIT(*(char *) sign); - sign = (BITVECP) (((char *) sign) + 1); + size += number_of_ones[(unsigned char) sign[i]]; ); return size; } @@ -217,11 +228,12 @@ static int hemdistsign(BITVECP a, BITVECP b) { int i, + diff, dist = 0; - ALOOPBIT( - if (GETBIT(a, i) != GETBIT(b, i)) - dist++; + ALOOPBYTE( + diff = (unsigned char) (a[i] ^ b[i]); + dist += number_of_ones[diff]; ); return dist; } diff --git a/contrib/ltree/ltree.h b/contrib/ltree/ltree.h index 0400db8b77..8f9ba4074f 100644 --- a/contrib/ltree/ltree.h +++ b/contrib/ltree/ltree.h @@ -177,10 +177,6 @@ typedef unsigned char *BITVECP; for(i=0;i> i & 0x01 ) @@ -238,10 +234,6 @@ typedef unsigned char ABITVEC[ASIGLEN]; for(i=0;i> i & 0x01 ) #define CLRBIT(x,i) GETBYTE(x,i) &= ~( 0x01 << ( (i) % BITBYTE ) ) diff --git a/contrib/pg_trgm/trgm_gist.c b/contrib/pg_trgm/trgm_gist.c index 9f1c20cf04..e7c21a435b 100644 --- a/contrib/pg_trgm/trgm_gist.c +++ b/contrib/pg_trgm/trgm_gist.c @@ -36,16 +36,25 @@ Datum gtrgm_picksplit(PG_FUNCTION_ARGS); #define GETENTRY(vec,pos) ((TRGM *) DatumGetPointer((vec)->vector[(pos)].key)) -#define SUMBIT(val) ( \ - GETBITBYTE(val,0) + \ - GETBITBYTE(val,1) + \ - GETBITBYTE(val,2) + \ - GETBITBYTE(val,3) + \ - GETBITBYTE(val,4) + \ - GETBITBYTE(val,5) + \ - GETBITBYTE(val,6) + \ - GETBITBYTE(val,7) \ -) +/* Number of one-bits in an unsigned byte */ +static const uint8 number_of_ones[256] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 +}; Datum @@ -298,8 +307,7 @@ sizebitvec(BITVECP sign) i; LOOPBYTE( - size += SUMBIT(*(char *) sign); - sign = (BITVECP) (((char *) sign) + 1); + size += number_of_ones[(unsigned char) sign[i]]; ); return size; } @@ -308,11 +316,12 @@ static int hemdistsign(BITVECP a, BITVECP b) { int i, + diff, dist = 0; - LOOPBIT( - if (GETBIT(a, i) != GETBIT(b, i)) - dist++; + LOOPBYTE( + diff = (unsigned char) (a[i] ^ b[i]); + dist += number_of_ones[diff]; ); return dist; } diff --git a/contrib/tsearch2/gistidx.c b/contrib/tsearch2/gistidx.c index a01d06d65e..6aabae2777 100644 --- a/contrib/tsearch2/gistidx.c +++ b/contrib/tsearch2/gistidx.c @@ -42,16 +42,26 @@ PG_FUNCTION_INFO_V1(gtsvector_picksplit); Datum gtsvector_picksplit(PG_FUNCTION_ARGS); #define GETENTRY(vec,pos) ((GISTTYPE *) DatumGetPointer((vec)->vector[(pos)].key)) -#define SUMBIT(val) ( \ - GETBITBYTE(val,0) + \ - GETBITBYTE(val,1) + \ - GETBITBYTE(val,2) + \ - GETBITBYTE(val,3) + \ - GETBITBYTE(val,4) + \ - GETBITBYTE(val,5) + \ - GETBITBYTE(val,6) + \ - GETBITBYTE(val,7) \ -) + +/* Number of one-bits in an unsigned byte */ +static const uint8 number_of_ones[256] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 +}; static int4 sizebitvec(BITVECP sign); @@ -435,8 +445,7 @@ sizebitvec(BITVECP sign) i; LOOPBYTE( - size += SUMBIT(*(char *) sign); - sign = (BITVECP) (((char *) sign) + 1); + size += number_of_ones[(unsigned char) sign[i]]; ); return size; } @@ -445,11 +454,12 @@ static int hemdistsign(BITVECP a, BITVECP b) { int i, + diff, dist = 0; - LOOPBIT( - if (GETBIT(a, i) != GETBIT(b, i)) - dist++; + LOOPBYTE( + diff = (unsigned char) (a[i] ^ b[i]); + dist += number_of_ones[diff]; ); return dist; } diff --git a/contrib/tsearch2/gistidx.h b/contrib/tsearch2/gistidx.h index 3f72252b05..142318b8c8 100644 --- a/contrib/tsearch2/gistidx.h +++ b/contrib/tsearch2/gistidx.h @@ -21,10 +21,6 @@ typedef char *BITVECP; for(i=0;i> (i) & 0x01 )