From 0b846521934c7fb273c26675c5054ea2990366d1 Mon Sep 17 00:00:00 2001 From: David Rowley Date: Tue, 27 Jan 2026 15:08:09 +1300 Subject: [PATCH v6 3/3] Introduce deform_bench test module For benchmaring tuple deformation. --- src/test/modules/deform_bench/.gitignore | 4 + src/test/modules/deform_bench/Makefile | 21 ++++ .../deform_bench/deform_bench--1.0.sql | 8 ++ src/test/modules/deform_bench/deform_bench.c | 105 ++++++++++++++++++ .../modules/deform_bench/deform_bench.control | 4 + src/test/modules/deform_bench/meson.build | 22 ++++ src/test/modules/meson.build | 1 + 7 files changed, 165 insertions(+) create mode 100644 src/test/modules/deform_bench/.gitignore create mode 100644 src/test/modules/deform_bench/Makefile create mode 100644 src/test/modules/deform_bench/deform_bench--1.0.sql create mode 100644 src/test/modules/deform_bench/deform_bench.c create mode 100644 src/test/modules/deform_bench/deform_bench.control create mode 100644 src/test/modules/deform_bench/meson.build diff --git a/src/test/modules/deform_bench/.gitignore b/src/test/modules/deform_bench/.gitignore new file mode 100644 index 00000000000..5dcb3ff9723 --- /dev/null +++ b/src/test/modules/deform_bench/.gitignore @@ -0,0 +1,4 @@ +# Generated subdirectories +/log/ +/results/ +/tmp_check/ diff --git a/src/test/modules/deform_bench/Makefile b/src/test/modules/deform_bench/Makefile new file mode 100644 index 00000000000..b5fc0f7a583 --- /dev/null +++ b/src/test/modules/deform_bench/Makefile @@ -0,0 +1,21 @@ +# src/test/modules/deform_bench/Makefile + +MODULE_big = deform_bench +OBJS = deform_bench.o + +EXTENSION = deform_bench +DATA = deform_bench--1.0.sql +PGFILEDESC = "deform_bench - tuple deform benchmarking" + +REGRESS = deform_bench + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = src/test/modules/deform_bench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/src/test/modules/deform_bench/deform_bench--1.0.sql b/src/test/modules/deform_bench/deform_bench--1.0.sql new file mode 100644 index 00000000000..492b71dba3b --- /dev/null +++ b/src/test/modules/deform_bench/deform_bench--1.0.sql @@ -0,0 +1,8 @@ +/* deform_bench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION deform_bench" to load this file. \quit + +CREATE FUNCTION deform_bench(tableoid Oid, attnum int[]) RETURNS FLOAT +AS 'MODULE_PATHNAME', 'deform_bench' +LANGUAGE C VOLATILE STRICT; diff --git a/src/test/modules/deform_bench/deform_bench.c b/src/test/modules/deform_bench/deform_bench.c new file mode 100644 index 00000000000..895ff3f4222 --- /dev/null +++ b/src/test/modules/deform_bench/deform_bench.c @@ -0,0 +1,105 @@ +/*------------------------------------------------------------------------- + * + * deform_bench.c + * + * for benchmarking tuple deformation routines + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include +#include + +#include "access/heapam.h" +#include "access/relscan.h" +#include "catalog/pg_am_d.h" +#include "catalog/pg_type_d.h" +#include "funcapi.h" +#include "miscadmin.h" +#include "utils/array.h" +#include "utils/arrayaccess.h" +#include "utils/builtins.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(deform_bench); + +Datum +deform_bench(PG_FUNCTION_ARGS) +{ + Oid tableoid = PG_GETARG_OID(0); + ArrayType *array = PG_GETARG_ARRAYTYPE_P(1); + TableScanDesc scan; + Relation rel; + TupleDesc tupdesc; + TupleTableSlot *slot; + Datum *elem_datums = NULL; + bool *elem_nulls = NULL; + int elem_count; + int *attnums; + clock_t start, end; + + rel = relation_open(tableoid, AccessShareLock); + + if (rel->rd_rel->relam != HEAP_TABLE_AM_OID) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("only heap AM is supported"))); + + tupdesc = RelationGetDescr(rel); + slot = MakeTupleTableSlot(tupdesc, &TTSOpsBufferHeapTuple); + scan = table_beginscan_strat(rel, GetActiveSnapshot(), 0, NULL, true, false); + + /* + * The array is used to allow callers to define how many atts to deform. + * e.g: '{1,10}'::int[] would deform attnum=1, then in a 2nd pass deform + * the remainder up to attnum=10. Passing an element as NULL means all + * attnums. This allows simulation of incremental deformation. Generally + * if you're passing an array with more than 1 element, then the array + * should be in ascending order. Doing something like '{10,1}' would mean + * we've already deformed 10 attributes and on the 2nd pass there's + * nothing to do since attnum=1 was already deformed in the first pass. + * + * You'll get an ERROR if you pass a number higher than the number of + * attributes in the table. + */ + deconstruct_array(array, + INT4OID, + sizeof(int32), + true, + 'i', + &elem_datums, + &elem_nulls, + &elem_count); + + attnums = palloc_array(int, elem_count); + + for (int i = 0; i < elem_count; i++) + { + /* Make a NULL element mean all attributes */ + if (elem_nulls[i]) + attnums[i] = tupdesc->natts; + else + attnums[i] = DatumGetInt32(elem_datums[i]); + } + + start = clock(); + + while (heap_getnextslot(scan, ForwardScanDirection, slot)) + { + CHECK_FOR_INTERRUPTS(); + + /* Deform in stages according to the attnums array */ + for (int i = 0; i < elem_count; i++) + slot_getsomeattrs_int(slot, attnums[i]); + } + + ExecDropSingleTupleTableSlot(slot); + table_endscan(scan); + relation_close(rel, AccessShareLock); + + end = clock(); + + /* Returns the number of milliseconds to run the test */ + PG_RETURN_FLOAT8((double) (end - start) / (CLOCKS_PER_SEC / 1000)); +} diff --git a/src/test/modules/deform_bench/deform_bench.control b/src/test/modules/deform_bench/deform_bench.control new file mode 100644 index 00000000000..a2023f9d738 --- /dev/null +++ b/src/test/modules/deform_bench/deform_bench.control @@ -0,0 +1,4 @@ +# deform_bench extension +comment = 'functions for benchmarking tuple deformation' +default_version = '1.0' +module_pathname = '$libdir/deform_bench' diff --git a/src/test/modules/deform_bench/meson.build b/src/test/modules/deform_bench/meson.build new file mode 100644 index 00000000000..82049585244 --- /dev/null +++ b/src/test/modules/deform_bench/meson.build @@ -0,0 +1,22 @@ +# Copyright (c) 2026, PostgreSQL Global Development Group + +deform_bench_sources = files( + 'deform_bench.c', +) + +if host_system == 'windows' + deform_bench_sources += rc_lib_gen.process(win32ver_rc, extra_args: [ + '--NAME', 'deform_bench', + '--FILEDESC', 'deform_bench - benchmarking tuple deformation',]) +endif + +deform_bench = shared_module('deform_bench', + deform_bench_sources, + kwargs: pg_test_mod_args, +) +test_install_libs += deform_bench + +test_install_data += files( + 'deform_bench--1.0.sql', + 'deform_bench.control', +) diff --git a/src/test/modules/meson.build b/src/test/modules/meson.build index 2634a519935..ef2b0af4581 100644 --- a/src/test/modules/meson.build +++ b/src/test/modules/meson.build @@ -2,6 +2,7 @@ subdir('brin') subdir('commit_ts') +subdir('deform_bench') subdir('delay_execution') subdir('dummy_index_am') subdir('dummy_seclabel') -- 2.51.0