bms_fixes.patch
application/octet-stream
Filename: bms_fixes.patch
Type: application/octet-stream
Part: 1
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/nodes/bitmapset.c | 11 | 9 |
| src/test/modules/test_bitmapset/test_bitmapset--1.0.sql | 9 | 0 |
| src/test/modules/test_bitmapset/test_bitmapset.c | 73 | 0 |
diff --git a/src/backend/nodes/bitmapset.c b/src/backend/nodes/bitmapset.c
index ac3e763de43..46b4ca4b0f1 100644
--- a/src/backend/nodes/bitmapset.c
+++ b/src/backend/nodes/bitmapset.c
@@ -1444,6 +1444,7 @@ bms_join(Bitmapset *a, Bitmapset *b)
int
bms_next_member(const Bitmapset *a, int prevbit)
{
+ int64 currbit;
int nwords;
bitmapword mask;
@@ -1452,13 +1453,13 @@ bms_next_member(const Bitmapset *a, int prevbit)
if (a == NULL)
return -2;
nwords = a->nwords;
- prevbit++;
- mask = (~(bitmapword) 0) << BITNUM(prevbit);
- for (int wordnum = WORDNUM(prevbit); wordnum < nwords; wordnum++)
+ currbit = (int64) prevbit + 1;
+ mask = (~(bitmapword) 0) << BITNUM(currbit);
+ for (int wordnum = WORDNUM(currbit); wordnum < nwords; wordnum++)
{
bitmapword w = a->words[wordnum];
- /* ignore bits before prevbit */
+ /* ignore bits before currbit */
w &= mask;
if (w != 0)
@@ -1505,6 +1506,7 @@ int
bms_prev_member(const Bitmapset *a, int prevbit)
{
int ushiftbits;
+ uint32 currbit;
bitmapword mask;
Assert(bms_is_valid_set(a));
@@ -1517,18 +1519,18 @@ bms_prev_member(const Bitmapset *a, int prevbit)
return -2;
/* Validate callers didn't give us something out of range */
- Assert(prevbit <= a->nwords * BITS_PER_BITMAPWORD);
+ Assert(prevbit <= (int64) a->nwords * BITS_PER_BITMAPWORD);
Assert(prevbit >= -1);
/* transform -1 to the highest possible bit we could have set */
if (prevbit == -1)
- prevbit = a->nwords * BITS_PER_BITMAPWORD - 1;
+ currbit = (uint32) a->nwords * BITS_PER_BITMAPWORD - 1;
else
- prevbit--;
+ currbit = prevbit - 1;
- ushiftbits = BITS_PER_BITMAPWORD - (BITNUM(prevbit) + 1);
+ ushiftbits = BITS_PER_BITMAPWORD - (BITNUM(currbit) + 1);
mask = (~(bitmapword) 0) >> ushiftbits;
- for (int wordnum = WORDNUM(prevbit); wordnum >= 0; wordnum--)
+ for (int wordnum = WORDNUM(currbit); wordnum >= 0; wordnum--)
{
bitmapword w = a->words[wordnum];
diff --git a/src/test/modules/test_bitmapset/test_bitmapset--1.0.sql b/src/test/modules/test_bitmapset/test_bitmapset--1.0.sql
index 6668bcef9a9..d6c0f739e13 100644
--- a/src/test/modules/test_bitmapset/test_bitmapset--1.0.sql
+++ b/src/test/modules/test_bitmapset/test_bitmapset--1.0.sql
@@ -3,6 +3,15 @@
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION test_bitmapset" to load this file. \quit
+-- Benchmark functions
+CREATE FUNCTION bench_bms_next_member(text, integer)
+RETURNS bigint
+AS 'MODULE_PATHNAME' LANGUAGE C;
+
+CREATE FUNCTION bench_bms_prev_member(text, integer)
+RETURNS bigint
+AS 'MODULE_PATHNAME' LANGUAGE C;
+
-- Bitmapset API functions
CREATE FUNCTION test_bms_make_singleton(integer)
RETURNS text STRICT
diff --git a/src/test/modules/test_bitmapset/test_bitmapset.c b/src/test/modules/test_bitmapset/test_bitmapset.c
index 4fe22ee64d2..990347a0f22 100644
--- a/src/test/modules/test_bitmapset/test_bitmapset.c
+++ b/src/test/modules/test_bitmapset/test_bitmapset.c
@@ -17,6 +17,7 @@
#include "postgres.h"
#include <stddef.h>
+#include <time.h>
#include "catalog/pg_type.h"
#include "common/pg_prng.h"
#include "utils/array.h"
@@ -27,8 +28,13 @@
#include "utils/builtins.h"
#include "utils/timestamp.h"
+
PG_MODULE_MAGIC;
+/* Benchmark functions */
+PG_FUNCTION_INFO_V1(bench_bms_next_member);
+PG_FUNCTION_INFO_V1(bench_bms_prev_member);
+
/* Bitmapset API functions in order of appearance in bitmapset.c */
PG_FUNCTION_INFO_V1(test_bms_make_singleton);
PG_FUNCTION_INFO_V1(test_bms_add_member);
@@ -105,6 +111,73 @@ PG_FUNCTION_INFO_V1(test_random_shift_operations);
#define PG_RETURN_BITMAPSET_AS_TEXT(bms) \
PG_RETURN_TEXT_P(BITMAPSET_TO_TEXT(bms))
+#define NANOSEC_PER_SEC 1000000000
+
+int64 get_clock_diff(struct timespec* t1, struct timespec* t2);
+
+int64
+get_clock_diff(struct timespec* t1, struct timespec* t2)
+{
+ int64_t nanosec = (t1->tv_sec - t2->tv_sec) * NANOSEC_PER_SEC;
+ nanosec += (t1->tv_nsec - t2->tv_nsec);
+
+ return nanosec;
+}
+
+Datum
+bench_bms_next_member(PG_FUNCTION_ARGS)
+{
+ Bitmapset* bms = PG_ARG_GETBITMAPSET(0);
+ int32 loops = PG_GETARG_INT32(1);
+
+ struct timespec start, end;
+ int64 nanoseconds;
+ int64 counter = 0;
+
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start);
+
+ for (int i = 0; i < loops; i++)
+ {
+ int m = -1;
+ while ((m = bms_next_member(bms, m)) >= 0)
+ {
+ counter++;
+ }
+ }
+
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end);
+ nanoseconds = get_clock_diff(&end, &start);
+
+ PG_RETURN_INT64(nanoseconds);
+}
+
+Datum
+bench_bms_prev_member(PG_FUNCTION_ARGS)
+{
+ Bitmapset* bms = PG_ARG_GETBITMAPSET(0);
+ int32 loops = PG_GETARG_INT32(1);
+
+ struct timespec start, end;
+ int64 nanoseconds;
+ int64 counter = 0;
+
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start);
+
+ for (int i = 0; i < loops; i++)
+ {
+ int m = -1;
+ while ((m = bms_prev_member(bms, m)) >= 0)
+ {
+ counter++;
+ }
+ }
+
+ clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end);
+ nanoseconds = get_clock_diff(&end, &start);
+
+ PG_RETURN_INT64(nanoseconds);
+}
+
/*
* Individual test functions for each bitmapset API function
*