From e31a67e4b09a20d6c1922cfe9e729c08e50ffad4 Mon Sep 17 00:00:00 2001 From: Yuya Watari Date: Tue, 14 Mar 2023 15:12:18 +0900 Subject: [PATCH v1] Remove bms_is_empty_internal() function calls Originally, we checked whether the result of the Bitmapset operation was empty or not by calling the bms_is_empty_internal() function. However, these calls lead to unnecessary looping over the result Bitmapset. This commit reduces such redundant calls and improves the performance. --- src/backend/nodes/bitmapset.c | 78 ++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/src/backend/nodes/bitmapset.c b/src/backend/nodes/bitmapset.c index 7ba3cf635b..b8155ae869 100644 --- a/src/backend/nodes/bitmapset.c +++ b/src/backend/nodes/bitmapset.c @@ -64,8 +64,6 @@ #error "invalid BITS_PER_BITMAPWORD" #endif -static bool bms_is_empty_internal(const Bitmapset *a); - /* * bms_copy - make a palloc'd copy of a bitmapset @@ -263,6 +261,7 @@ bms_intersect(const Bitmapset *a, const Bitmapset *b) const Bitmapset *other; int resultlen; int i; + bitmapword bitwise_or = 0; /* Handle cases where either input is NULL */ if (a == NULL || b == NULL) @@ -281,9 +280,17 @@ bms_intersect(const Bitmapset *a, const Bitmapset *b) /* And intersect the longer input with the result */ resultlen = result->nwords; for (i = 0; i < resultlen; i++) - result->words[i] &= other->words[i]; + { + bitmapword w = (result->words[i] &= other->words[i]); + + /* + * Compute bitwise OR of all bitmapwords to determine if the result + * is empty + */ + bitwise_or |= w; + } /* If we computed an empty result, we must return NULL */ - if (bms_is_empty_internal(result)) + if (bitwise_or == 0) { pfree(result); return NULL; @@ -711,30 +718,6 @@ bms_membership(const Bitmapset *a) return result; } -/* - * bms_is_empty_internal - is a set empty? - * - * This is now used only locally, to detect cases where a function has - * computed an empty set that we must now get rid of. Hence, we can - * assume the input isn't NULL. - */ -static bool -bms_is_empty_internal(const Bitmapset *a) -{ - int nwords; - int wordnum; - - nwords = a->nwords; - for (wordnum = 0; wordnum < nwords; wordnum++) - { - bitmapword w = a->words[wordnum]; - - if (w != 0) - return false; - } - return true; -} - /* * These operations all "recycle" their non-const inputs, ie, either @@ -793,6 +776,7 @@ bms_del_member(Bitmapset *a, int x) { int wordnum, bitnum; + bitmapword bitwise_or = 0; if (x < 0) elog(ERROR, "negative bitmapset member not allowed"); @@ -801,9 +785,17 @@ bms_del_member(Bitmapset *a, int x) wordnum = WORDNUM(x); bitnum = BITNUM(x); if (wordnum < a->nwords) - a->words[wordnum] &= ~((bitmapword) 1 << bitnum); + { + bitmapword w = (a->words[wordnum] &= ~((bitmapword) 1 << bitnum)); + + /* + * Compute bitwise OR of all bitmapwords to determine if the result + * is empty + */ + bitwise_or |= w; + } /* If we computed an empty result, we must return NULL */ - if (bms_is_empty_internal(a)) + if (bitwise_or == 0) { pfree(a); return NULL; @@ -929,6 +921,7 @@ bms_int_members(Bitmapset *a, const Bitmapset *b) { int shortlen; int i; + bitmapword bitwise_or = 0; /* Handle cases where either input is NULL */ if (a == NULL) @@ -941,11 +934,19 @@ bms_int_members(Bitmapset *a, const Bitmapset *b) /* Intersect b into a; we need never copy */ shortlen = Min(a->nwords, b->nwords); for (i = 0; i < shortlen; i++) - a->words[i] &= b->words[i]; + { + bitmapword w = (a->words[i] &= b->words[i]); + + /* + * Compute bitwise OR of all bitmapwords to determine if the result + * is empty + */ + bitwise_or |= w; + } for (; i < a->nwords; i++) a->words[i] = 0; /* If we computed an empty result, we must return NULL */ - if (bms_is_empty_internal(a)) + if (bitwise_or == 0) { pfree(a); return NULL; @@ -961,6 +962,7 @@ bms_del_members(Bitmapset *a, const Bitmapset *b) { int shortlen; int i; + bitmapword bitwise_or = 0; /* Handle cases where either input is NULL */ if (a == NULL) @@ -970,9 +972,17 @@ bms_del_members(Bitmapset *a, const Bitmapset *b) /* Remove b's bits from a; we need never copy */ shortlen = Min(a->nwords, b->nwords); for (i = 0; i < shortlen; i++) - a->words[i] &= ~b->words[i]; + { + bitmapword w = (a->words[i] &= ~b->words[i]); + + /* + * Compute bitwise OR of all bitmapwords to determine if the result + * is empty + */ + bitwise_or |= w; + } /* If we computed an empty result, we must return NULL */ - if (bms_is_empty_internal(a)) + if (bitwise_or == 0) { pfree(a); return NULL; -- 2.39.2.windows.1