From d2ea8d719f1981937f3205150b0870d38499fabc Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Thu, 10 Aug 2017 15:40:30 +1200 Subject: [PATCH] Teach Bitmapset to skip leading zeroes in some cases. Some of the algorithms in bitmapset.c can avoid scanning most of their words in the not-uncommon case of singleton or fortunately organized sparse sets, if we keep track of the first occupied word. * Quick hack, not for commit! * Author: Thomas Munro --- src/backend/nodes/bitmapset.c | 22 ++++++++++++++++------ src/include/nodes/bitmapset.h | 1 + 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/backend/nodes/bitmapset.c b/src/backend/nodes/bitmapset.c index bf8545d4378..8bf8271f88f 100644 --- a/src/backend/nodes/bitmapset.c +++ b/src/backend/nodes/bitmapset.c @@ -187,6 +187,7 @@ bms_make_singleton(int x) wordnum = WORDNUM(x); bitnum = BITNUM(x); result = (Bitmapset *) palloc0(BITMAPSET_SIZE(wordnum + 1)); + result->first_non_empty_wordnum = wordnum; result->nwords = wordnum + 1; result->words[wordnum] = ((bitmapword) 1 << bitnum); return result; @@ -310,6 +311,7 @@ bms_is_subset(const Bitmapset *a, const Bitmapset *b) int shortlen; int longlen; int i; + int start; /* Handle cases where either input is NULL */ if (a == NULL) @@ -318,7 +320,8 @@ bms_is_subset(const Bitmapset *a, const Bitmapset *b) return bms_is_empty(a); /* Check common words */ shortlen = Min(a->nwords, b->nwords); - for (i = 0; i < shortlen; i++) + start = Min(a->first_non_empty_wordnum, b->first_non_empty_wordnum); + for (i = start; i < shortlen; i++) { if ((a->words[i] & ~b->words[i]) != 0) return false; @@ -444,13 +447,15 @@ bms_overlap(const Bitmapset *a, const Bitmapset *b) { int shortlen; int i; + int start; /* Handle cases where either input is NULL */ if (a == NULL || b == NULL) return false; /* Check words in common */ shortlen = Min(a->nwords, b->nwords); - for (i = 0; i < shortlen; i++) + start = Max(a->first_non_empty_wordnum, b->first_non_empty_wordnum); + for (i = start; i < shortlen; i++) { if ((a->words[i] & b->words[i]) != 0) return true; @@ -611,7 +616,7 @@ bms_num_members(const Bitmapset *a) if (a == NULL) return 0; nwords = a->nwords; - for (wordnum = 0; wordnum < nwords; wordnum++) + for (wordnum = a->first_non_empty_wordnum; wordnum < nwords; wordnum++) { bitmapword w = a->words[wordnum]; @@ -640,7 +645,7 @@ bms_membership(const Bitmapset *a) if (a == NULL) return BMS_EMPTY_SET; nwords = a->nwords; - for (wordnum = 0; wordnum < nwords; wordnum++) + for (wordnum = a->first_non_empty_wordnum; wordnum < nwords; wordnum++) { bitmapword w = a->words[wordnum]; @@ -668,7 +673,7 @@ bms_is_empty(const Bitmapset *a) if (a == NULL) return true; nwords = a->nwords; - for (wordnum = 0; wordnum < nwords; wordnum++) + for (wordnum = a->first_non_empty_wordnum; wordnum < nwords; wordnum++) { bitmapword w = a->words[wordnum]; @@ -707,6 +712,9 @@ bms_add_member(Bitmapset *a, int x) wordnum = WORDNUM(x); bitnum = BITNUM(x); + if (wordnum < a->first_non_empty_wordnum) + a->first_non_empty_wordnum = wordnum; + /* enlarge the set if necessary */ if (wordnum >= a->nwords) { @@ -779,6 +787,8 @@ bms_add_members(Bitmapset *a, const Bitmapset *b) otherlen = other->nwords; for (i = 0; i < otherlen; i++) result->words[i] |= other->words[i]; + result->first_non_empty_wordnum = + Min(result->first_non_empty_wordnum, other->first_non_empty_wordnum); if (result != a) pfree(a); return result; @@ -890,7 +900,7 @@ bms_first_member(Bitmapset *a) if (a == NULL) return -1; nwords = a->nwords; - for (wordnum = 0; wordnum < nwords; wordnum++) + for (wordnum = a->first_non_empty_wordnum; wordnum < nwords; wordnum++) { bitmapword w = a->words[wordnum]; diff --git a/src/include/nodes/bitmapset.h b/src/include/nodes/bitmapset.h index aa3fb253c27..fd2ed729de5 100644 --- a/src/include/nodes/bitmapset.h +++ b/src/include/nodes/bitmapset.h @@ -37,6 +37,7 @@ typedef int32 signedbitmapword; /* must be the matching signed type */ typedef struct Bitmapset { int nwords; /* number of words in array */ + int first_non_empty_wordnum; /* first non-zero word */ bitmapword words[FLEXIBLE_ARRAY_MEMBER]; /* really [nwords] */ } Bitmapset; -- 2.13.2