public inbox for [email protected]help / color / mirror / Atom feed
[PATCH v2 1/1] resownerbench 43+ messages / 2 participants [nested] [flat]
* [PATCH v2 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..e3c0a9710ee --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000 * 10), + (0, 5, 2000000 * 10), + (0, 10, 1000000 * 10), + (0, 60, 100000 * 10), + (0, 70, 100000 * 10), + (0, 100, 100000 * 10), + (0, 1000, 10000 * 10), + (0, 10000, 1000 * 10), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000 * 10), + (9, 100, 100000 * 10), + (9, 1000, 10000 * 10), + (9, 10000, 1000 * 10), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000 * 10), + (65, 100, 100000 * 10), + (65, 1000, 10000 * 10), + (65, 10000, 1000 * 10) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------F30A5443A5D524A5CBC51AE7-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..18c54e13fc9 --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000), + (0, 5, 2000000), + (0, 10, 1000000), + (0, 60, 100000), + (0, 70, 100000), + (0, 100, 100000), + (0, 1000, 10000), + (0, 10000, 1000), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000), + (9, 100, 100000), + (9, 1000, 10000), + (9, 10000, 1000), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000), + (65, 100, 100000), + (65, 1000, 10000), + (65, 10000, 1000) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------1104342304EC6341F5D7C60C-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH v2 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..e3c0a9710ee --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000 * 10), + (0, 5, 2000000 * 10), + (0, 10, 1000000 * 10), + (0, 60, 100000 * 10), + (0, 70, 100000 * 10), + (0, 100, 100000 * 10), + (0, 1000, 10000 * 10), + (0, 10000, 1000 * 10), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000 * 10), + (9, 100, 100000 * 10), + (9, 1000, 10000 * 10), + (9, 10000, 1000 * 10), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000 * 10), + (65, 100, 100000 * 10), + (65, 1000, 10000 * 10), + (65, 10000, 1000 * 10) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------F30A5443A5D524A5CBC51AE7-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..18c54e13fc9 --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000), + (0, 5, 2000000), + (0, 10, 1000000), + (0, 60, 100000), + (0, 70, 100000), + (0, 100, 100000), + (0, 1000, 10000), + (0, 10000, 1000), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000), + (9, 100, 100000), + (9, 1000, 10000), + (9, 10000, 1000), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000), + (65, 100, 100000), + (65, 1000, 10000), + (65, 10000, 1000) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------1104342304EC6341F5D7C60C-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH v2 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..e3c0a9710ee --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000 * 10), + (0, 5, 2000000 * 10), + (0, 10, 1000000 * 10), + (0, 60, 100000 * 10), + (0, 70, 100000 * 10), + (0, 100, 100000 * 10), + (0, 1000, 10000 * 10), + (0, 10000, 1000 * 10), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000 * 10), + (9, 100, 100000 * 10), + (9, 1000, 10000 * 10), + (9, 10000, 1000 * 10), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000 * 10), + (65, 100, 100000 * 10), + (65, 1000, 10000 * 10), + (65, 10000, 1000 * 10) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------F30A5443A5D524A5CBC51AE7-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..18c54e13fc9 --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000), + (0, 5, 2000000), + (0, 10, 1000000), + (0, 60, 100000), + (0, 70, 100000), + (0, 100, 100000), + (0, 1000, 10000), + (0, 10000, 1000), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000), + (9, 100, 100000), + (9, 1000, 10000), + (9, 10000, 1000), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000), + (65, 100, 100000), + (65, 1000, 10000), + (65, 10000, 1000) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------1104342304EC6341F5D7C60C-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH v2 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..e3c0a9710ee --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000 * 10), + (0, 5, 2000000 * 10), + (0, 10, 1000000 * 10), + (0, 60, 100000 * 10), + (0, 70, 100000 * 10), + (0, 100, 100000 * 10), + (0, 1000, 10000 * 10), + (0, 10000, 1000 * 10), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000 * 10), + (9, 100, 100000 * 10), + (9, 1000, 10000 * 10), + (9, 10000, 1000 * 10), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000 * 10), + (65, 100, 100000 * 10), + (65, 1000, 10000 * 10), + (65, 10000, 1000 * 10) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------F30A5443A5D524A5CBC51AE7-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..18c54e13fc9 --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000), + (0, 5, 2000000), + (0, 10, 1000000), + (0, 60, 100000), + (0, 70, 100000), + (0, 100, 100000), + (0, 1000, 10000), + (0, 10000, 1000), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000), + (9, 100, 100000), + (9, 1000, 10000), + (9, 10000, 1000), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000), + (65, 100, 100000), + (65, 1000, 10000), + (65, 10000, 1000) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------1104342304EC6341F5D7C60C-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH v2 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..e3c0a9710ee --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000 * 10), + (0, 5, 2000000 * 10), + (0, 10, 1000000 * 10), + (0, 60, 100000 * 10), + (0, 70, 100000 * 10), + (0, 100, 100000 * 10), + (0, 1000, 10000 * 10), + (0, 10000, 1000 * 10), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000 * 10), + (9, 100, 100000 * 10), + (9, 1000, 10000 * 10), + (9, 10000, 1000 * 10), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000 * 10), + (65, 100, 100000 * 10), + (65, 1000, 10000 * 10), + (65, 10000, 1000 * 10) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------F30A5443A5D524A5CBC51AE7-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..18c54e13fc9 --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000), + (0, 5, 2000000), + (0, 10, 1000000), + (0, 60, 100000), + (0, 70, 100000), + (0, 100, 100000), + (0, 1000, 10000), + (0, 10000, 1000), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000), + (9, 100, 100000), + (9, 1000, 10000), + (9, 10000, 1000), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000), + (65, 100, 100000), + (65, 1000, 10000), + (65, 10000, 1000) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------1104342304EC6341F5D7C60C-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH v2 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..e3c0a9710ee --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000 * 10), + (0, 5, 2000000 * 10), + (0, 10, 1000000 * 10), + (0, 60, 100000 * 10), + (0, 70, 100000 * 10), + (0, 100, 100000 * 10), + (0, 1000, 10000 * 10), + (0, 10000, 1000 * 10), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000 * 10), + (9, 100, 100000 * 10), + (9, 1000, 10000 * 10), + (9, 10000, 1000 * 10), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000 * 10), + (65, 100, 100000 * 10), + (65, 1000, 10000 * 10), + (65, 10000, 1000 * 10) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------F30A5443A5D524A5CBC51AE7-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..18c54e13fc9 --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000), + (0, 5, 2000000), + (0, 10, 1000000), + (0, 60, 100000), + (0, 70, 100000), + (0, 100, 100000), + (0, 1000, 10000), + (0, 10000, 1000), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000), + (9, 100, 100000), + (9, 1000, 10000), + (9, 10000, 1000), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000), + (65, 100, 100000), + (65, 1000, 10000), + (65, 10000, 1000) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------1104342304EC6341F5D7C60C-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH v2 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..e3c0a9710ee --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000 * 10), + (0, 5, 2000000 * 10), + (0, 10, 1000000 * 10), + (0, 60, 100000 * 10), + (0, 70, 100000 * 10), + (0, 100, 100000 * 10), + (0, 1000, 10000 * 10), + (0, 10000, 1000 * 10), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000 * 10), + (9, 100, 100000 * 10), + (9, 1000, 10000 * 10), + (9, 10000, 1000 * 10), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000 * 10), + (65, 100, 100000 * 10), + (65, 1000, 10000 * 10), + (65, 10000, 1000 * 10) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------F30A5443A5D524A5CBC51AE7-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..18c54e13fc9 --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000), + (0, 5, 2000000), + (0, 10, 1000000), + (0, 60, 100000), + (0, 70, 100000), + (0, 100, 100000), + (0, 1000, 10000), + (0, 10000, 1000), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000), + (9, 100, 100000), + (9, 1000, 10000), + (9, 10000, 1000), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000), + (65, 100, 100000), + (65, 1000, 10000), + (65, 10000, 1000) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------1104342304EC6341F5D7C60C-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH v2 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..e3c0a9710ee --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000 * 10), + (0, 5, 2000000 * 10), + (0, 10, 1000000 * 10), + (0, 60, 100000 * 10), + (0, 70, 100000 * 10), + (0, 100, 100000 * 10), + (0, 1000, 10000 * 10), + (0, 10000, 1000 * 10), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000 * 10), + (9, 100, 100000 * 10), + (9, 1000, 10000 * 10), + (9, 10000, 1000 * 10), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000 * 10), + (65, 100, 100000 * 10), + (65, 1000, 10000 * 10), + (65, 10000, 1000 * 10) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------F30A5443A5D524A5CBC51AE7-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..18c54e13fc9 --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000), + (0, 5, 2000000), + (0, 10, 1000000), + (0, 60, 100000), + (0, 70, 100000), + (0, 100, 100000), + (0, 1000, 10000), + (0, 10000, 1000), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000), + (9, 100, 100000), + (9, 1000, 10000), + (9, 10000, 1000), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000), + (65, 100, 100000), + (65, 1000, 10000), + (65, 10000, 1000) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------1104342304EC6341F5D7C60C-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH v2 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..e3c0a9710ee --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000 * 10), + (0, 5, 2000000 * 10), + (0, 10, 1000000 * 10), + (0, 60, 100000 * 10), + (0, 70, 100000 * 10), + (0, 100, 100000 * 10), + (0, 1000, 10000 * 10), + (0, 10000, 1000 * 10), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000 * 10), + (9, 100, 100000 * 10), + (9, 1000, 10000 * 10), + (9, 10000, 1000 * 10), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000 * 10), + (65, 100, 100000 * 10), + (65, 1000, 10000 * 10), + (65, 10000, 1000 * 10) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------F30A5443A5D524A5CBC51AE7-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..18c54e13fc9 --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000), + (0, 5, 2000000), + (0, 10, 1000000), + (0, 60, 100000), + (0, 70, 100000), + (0, 100, 100000), + (0, 1000, 10000), + (0, 10000, 1000), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000), + (9, 100, 100000), + (9, 1000, 10000), + (9, 10000, 1000), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000), + (65, 100, 100000), + (65, 1000, 10000), + (65, 10000, 1000) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------1104342304EC6341F5D7C60C-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH v2 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..e3c0a9710ee --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000 * 10), + (0, 5, 2000000 * 10), + (0, 10, 1000000 * 10), + (0, 60, 100000 * 10), + (0, 70, 100000 * 10), + (0, 100, 100000 * 10), + (0, 1000, 10000 * 10), + (0, 10000, 1000 * 10), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000 * 10), + (9, 100, 100000 * 10), + (9, 1000, 10000 * 10), + (9, 10000, 1000 * 10), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000 * 10), + (65, 100, 100000 * 10), + (65, 1000, 10000 * 10), + (65, 10000, 1000 * 10) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------F30A5443A5D524A5CBC51AE7-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..18c54e13fc9 --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000), + (0, 5, 2000000), + (0, 10, 1000000), + (0, 60, 100000), + (0, 70, 100000), + (0, 100, 100000), + (0, 1000, 10000), + (0, 10000, 1000), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000), + (9, 100, 100000), + (9, 1000, 10000), + (9, 10000, 1000), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000), + (65, 100, 100000), + (65, 1000, 10000), + (65, 10000, 1000) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------1104342304EC6341F5D7C60C-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH v2 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..e3c0a9710ee --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000 * 10), + (0, 5, 2000000 * 10), + (0, 10, 1000000 * 10), + (0, 60, 100000 * 10), + (0, 70, 100000 * 10), + (0, 100, 100000 * 10), + (0, 1000, 10000 * 10), + (0, 10000, 1000 * 10), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000 * 10), + (9, 100, 100000 * 10), + (9, 1000, 10000 * 10), + (9, 10000, 1000 * 10), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000 * 10), + (65, 100, 100000 * 10), + (65, 1000, 10000 * 10), + (65, 10000, 1000 * 10) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------F30A5443A5D524A5CBC51AE7-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..18c54e13fc9 --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000), + (0, 5, 2000000), + (0, 10, 1000000), + (0, 60, 100000), + (0, 70, 100000), + (0, 100, 100000), + (0, 1000, 10000), + (0, 10000, 1000), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000), + (9, 100, 100000), + (9, 1000, 10000), + (9, 10000, 1000), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000), + (65, 100, 100000), + (65, 1000, 10000), + (65, 10000, 1000) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------1104342304EC6341F5D7C60C-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH v2 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..e3c0a9710ee --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000 * 10), + (0, 5, 2000000 * 10), + (0, 10, 1000000 * 10), + (0, 60, 100000 * 10), + (0, 70, 100000 * 10), + (0, 100, 100000 * 10), + (0, 1000, 10000 * 10), + (0, 10000, 1000 * 10), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000 * 10), + (9, 100, 100000 * 10), + (9, 1000, 10000 * 10), + (9, 10000, 1000 * 10), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000 * 10), + (65, 100, 100000 * 10), + (65, 1000, 10000 * 10), + (65, 10000, 1000 * 10) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------F30A5443A5D524A5CBC51AE7-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..18c54e13fc9 --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000), + (0, 5, 2000000), + (0, 10, 1000000), + (0, 60, 100000), + (0, 70, 100000), + (0, 100, 100000), + (0, 1000, 10000), + (0, 10000, 1000), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000), + (9, 100, 100000), + (9, 1000, 10000), + (9, 10000, 1000), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000), + (65, 100, 100000), + (65, 1000, 10000), + (65, 10000, 1000) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------1104342304EC6341F5D7C60C-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH v2 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..e3c0a9710ee --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000 * 10), + (0, 5, 2000000 * 10), + (0, 10, 1000000 * 10), + (0, 60, 100000 * 10), + (0, 70, 100000 * 10), + (0, 100, 100000 * 10), + (0, 1000, 10000 * 10), + (0, 10000, 1000 * 10), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000 * 10), + (9, 100, 100000 * 10), + (9, 1000, 10000 * 10), + (9, 10000, 1000 * 10), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000 * 10), + (65, 100, 100000 * 10), + (65, 1000, 10000 * 10), + (65, 10000, 1000 * 10) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------F30A5443A5D524A5CBC51AE7-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..18c54e13fc9 --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000), + (0, 5, 2000000), + (0, 10, 1000000), + (0, 60, 100000), + (0, 70, 100000), + (0, 100, 100000), + (0, 1000, 10000), + (0, 10000, 1000), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000), + (9, 100, 100000), + (9, 1000, 10000), + (9, 10000, 1000), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000), + (65, 100, 100000), + (65, 1000, 10000), + (65, 10000, 1000) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------1104342304EC6341F5D7C60C-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH v2 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..e3c0a9710ee --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000 * 10), + (0, 5, 2000000 * 10), + (0, 10, 1000000 * 10), + (0, 60, 100000 * 10), + (0, 70, 100000 * 10), + (0, 100, 100000 * 10), + (0, 1000, 10000 * 10), + (0, 10000, 1000 * 10), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000 * 10), + (9, 100, 100000 * 10), + (9, 1000, 10000 * 10), + (9, 10000, 1000 * 10), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000 * 10), + (65, 100, 100000 * 10), + (65, 1000, 10000 * 10), + (65, 10000, 1000 * 10) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------F30A5443A5D524A5CBC51AE7-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..18c54e13fc9 --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000), + (0, 5, 2000000), + (0, 10, 1000000), + (0, 60, 100000), + (0, 70, 100000), + (0, 100, 100000), + (0, 1000, 10000), + (0, 10000, 1000), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000), + (9, 100, 100000), + (9, 1000, 10000), + (9, 10000, 1000), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000), + (65, 100, 100000), + (65, 1000, 10000), + (65, 10000, 1000) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------1104342304EC6341F5D7C60C-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH v2 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..e3c0a9710ee --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000 * 10), + (0, 5, 2000000 * 10), + (0, 10, 1000000 * 10), + (0, 60, 100000 * 10), + (0, 70, 100000 * 10), + (0, 100, 100000 * 10), + (0, 1000, 10000 * 10), + (0, 10000, 1000 * 10), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000 * 10), + (9, 100, 100000 * 10), + (9, 1000, 10000 * 10), + (9, 10000, 1000 * 10), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000 * 10), + (65, 100, 100000 * 10), + (65, 1000, 10000 * 10), + (65, 10000, 1000 * 10) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------F30A5443A5D524A5CBC51AE7-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..18c54e13fc9 --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000), + (0, 5, 2000000), + (0, 10, 1000000), + (0, 60, 100000), + (0, 70, 100000), + (0, 100, 100000), + (0, 1000, 10000), + (0, 10000, 1000), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000), + (9, 100, 100000), + (9, 1000, 10000), + (9, 10000, 1000), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000), + (65, 100, 100000), + (65, 1000, 10000), + (65, 10000, 1000) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------1104342304EC6341F5D7C60C-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH v2 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..e3c0a9710ee --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000 * 10), + (0, 5, 2000000 * 10), + (0, 10, 1000000 * 10), + (0, 60, 100000 * 10), + (0, 70, 100000 * 10), + (0, 100, 100000 * 10), + (0, 1000, 10000 * 10), + (0, 10000, 1000 * 10), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000 * 10), + (9, 100, 100000 * 10), + (9, 1000, 10000 * 10), + (9, 10000, 1000 * 10), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000 * 10), + (65, 100, 100000 * 10), + (65, 1000, 10000 * 10), + (65, 10000, 1000 * 10) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------F30A5443A5D524A5CBC51AE7-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..18c54e13fc9 --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000), + (0, 5, 2000000), + (0, 10, 1000000), + (0, 60, 100000), + (0, 70, 100000), + (0, 100, 100000), + (0, 1000, 10000), + (0, 10000, 1000), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000), + (9, 100, 100000), + (9, 1000, 10000), + (9, 10000, 1000), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000), + (65, 100, 100000), + (65, 1000, 10000), + (65, 10000, 1000) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------1104342304EC6341F5D7C60C-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH v2 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..e3c0a9710ee --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000 * 10), + (0, 5, 2000000 * 10), + (0, 10, 1000000 * 10), + (0, 60, 100000 * 10), + (0, 70, 100000 * 10), + (0, 100, 100000 * 10), + (0, 1000, 10000 * 10), + (0, 10000, 1000 * 10), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000 * 10), + (9, 100, 100000 * 10), + (9, 1000, 10000 * 10), + (9, 10000, 1000 * 10), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000 * 10), + (65, 100, 100000 * 10), + (65, 1000, 10000 * 10), + (65, 10000, 1000 * 10) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------F30A5443A5D524A5CBC51AE7-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..18c54e13fc9 --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000), + (0, 5, 2000000), + (0, 10, 1000000), + (0, 60, 100000), + (0, 70, 100000), + (0, 100, 100000), + (0, 1000, 10000), + (0, 10000, 1000), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000), + (9, 100, 100000), + (9, 1000, 10000), + (9, 10000, 1000), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000), + (65, 100, 100000), + (65, 1000, 10000), + (65, 10000, 1000) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------1104342304EC6341F5D7C60C-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH v2 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..e3c0a9710ee --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000 * 10), + (0, 5, 2000000 * 10), + (0, 10, 1000000 * 10), + (0, 60, 100000 * 10), + (0, 70, 100000 * 10), + (0, 100, 100000 * 10), + (0, 1000, 10000 * 10), + (0, 10000, 1000 * 10), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000 * 10), + (9, 100, 100000 * 10), + (9, 1000, 10000 * 10), + (9, 10000, 1000 * 10), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000 * 10), + (65, 100, 100000 * 10), + (65, 1000, 10000 * 10), + (65, 10000, 1000 * 10) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------F30A5443A5D524A5CBC51AE7-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..18c54e13fc9 --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000), + (0, 5, 2000000), + (0, 10, 1000000), + (0, 60, 100000), + (0, 70, 100000), + (0, 100, 100000), + (0, 1000, 10000), + (0, 10000, 1000), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000), + (9, 100, 100000), + (9, 1000, 10000), + (9, 10000, 1000), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000), + (65, 100, 100000), + (65, 1000, 10000), + (65, 10000, 1000) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------1104342304EC6341F5D7C60C-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH v2 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..e3c0a9710ee --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000 * 10), + (0, 5, 2000000 * 10), + (0, 10, 1000000 * 10), + (0, 60, 100000 * 10), + (0, 70, 100000 * 10), + (0, 100, 100000 * 10), + (0, 1000, 10000 * 10), + (0, 10000, 1000 * 10), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000 * 10), + (9, 100, 100000 * 10), + (9, 1000, 10000 * 10), + (9, 10000, 1000 * 10), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000 * 10), + (65, 100, 100000 * 10), + (65, 1000, 10000 * 10), + (65, 10000, 1000 * 10) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------F30A5443A5D524A5CBC51AE7-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..18c54e13fc9 --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000), + (0, 5, 2000000), + (0, 10, 1000000), + (0, 60, 100000), + (0, 70, 100000), + (0, 100, 100000), + (0, 1000, 10000), + (0, 10000, 1000), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000), + (9, 100, 100000), + (9, 1000, 10000), + (9, 10000, 1000), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000), + (65, 100, 100000), + (65, 1000, 10000), + (65, 10000, 1000) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------1104342304EC6341F5D7C60C-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH v2 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..e3c0a9710ee --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000 * 10), + (0, 5, 2000000 * 10), + (0, 10, 1000000 * 10), + (0, 60, 100000 * 10), + (0, 70, 100000 * 10), + (0, 100, 100000 * 10), + (0, 1000, 10000 * 10), + (0, 10000, 1000 * 10), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000 * 10), + (9, 100, 100000 * 10), + (9, 1000, 10000 * 10), + (9, 10000, 1000 * 10), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000 * 10), + (65, 100, 100000 * 10), + (65, 1000, 10000 * 10), + (65, 10000, 1000 * 10) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------F30A5443A5D524A5CBC51AE7-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..18c54e13fc9 --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000), + (0, 5, 2000000), + (0, 10, 1000000), + (0, 60, 100000), + (0, 70, 100000), + (0, 100, 100000), + (0, 1000, 10000), + (0, 10000, 1000), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000), + (9, 100, 100000), + (9, 1000, 10000), + (9, 10000, 1000), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000), + (65, 100, 100000), + (65, 1000, 10000), + (65, 10000, 1000) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------1104342304EC6341F5D7C60C-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH v2 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..e3c0a9710ee --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000 * 10), + (0, 5, 2000000 * 10), + (0, 10, 1000000 * 10), + (0, 60, 100000 * 10), + (0, 70, 100000 * 10), + (0, 100, 100000 * 10), + (0, 1000, 10000 * 10), + (0, 10000, 1000 * 10), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000 * 10), + (9, 100, 100000 * 10), + (9, 1000, 10000 * 10), + (9, 10000, 1000 * 10), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000 * 10), + (65, 100, 100000 * 10), + (65, 1000, 10000 * 10), + (65, 10000, 1000 * 10) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------F30A5443A5D524A5CBC51AE7-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* [PATCH 1/1] resownerbench @ 2020-11-11 22:40 Heikki Linnakangas <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Heikki Linnakangas @ 2020-11-11 22:40 UTC (permalink / raw) --- contrib/resownerbench/Makefile | 17 ++ contrib/resownerbench/resownerbench--1.0.sql | 14 ++ contrib/resownerbench/resownerbench.c | 154 +++++++++++++++++++ contrib/resownerbench/resownerbench.control | 6 + contrib/resownerbench/snaptest.sql | 37 +++++ 5 files changed, 228 insertions(+) create mode 100644 contrib/resownerbench/Makefile create mode 100644 contrib/resownerbench/resownerbench--1.0.sql create mode 100644 contrib/resownerbench/resownerbench.c create mode 100644 contrib/resownerbench/resownerbench.control create mode 100644 contrib/resownerbench/snaptest.sql diff --git a/contrib/resownerbench/Makefile b/contrib/resownerbench/Makefile new file mode 100644 index 00000000000..9b0e1cfee1a --- /dev/null +++ b/contrib/resownerbench/Makefile @@ -0,0 +1,17 @@ +MODULE_big = resownerbench +OBJS = resownerbench.o + +EXTENSION = resownerbench +DATA = resownerbench--1.0.sql +PGFILEDESC = "resownerbench - benchmark for ResourceOwners" + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/resownerbench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/resownerbench/resownerbench--1.0.sql b/contrib/resownerbench/resownerbench--1.0.sql new file mode 100644 index 00000000000..d29182f5982 --- /dev/null +++ b/contrib/resownerbench/resownerbench--1.0.sql @@ -0,0 +1,14 @@ +/* contrib/resownerbench/resownerbench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION resownerbench" to load this file. \quit + +CREATE FUNCTION snapshotbench_lifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_lifo' +LANGUAGE C STRICT VOLATILE; + +CREATE FUNCTION snapshotbench_fifo(numkeep int, numsnaps int, numiters int) +RETURNS double precision +AS 'MODULE_PATHNAME', 'snapshotbench_fifo' +LANGUAGE C STRICT VOLATILE; diff --git a/contrib/resownerbench/resownerbench.c b/contrib/resownerbench/resownerbench.c new file mode 100644 index 00000000000..acfb6c39199 --- /dev/null +++ b/contrib/resownerbench/resownerbench.c @@ -0,0 +1,154 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "catalog/pg_statistic.h" +#include "executor/spi.h" +#include "funcapi.h" +#include "libpq/pqsignal.h" +#include "utils/catcache.h" +#include "utils/syscache.h" +#include "utils/timestamp.h" +#include "utils/snapmgr.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(snapshotbench_lifo); +PG_FUNCTION_INFO_V1(snapshotbench_fifo); + +/* + * ResourceOwner Performance test, using RegisterSnapshot(). + * + * This takes three parameters: numkeep, numsnaps, numiters. + * + * First, we register 'numkeep' snapshots. They are kept registed + * until the end of the test. Then, we repeatedly register and + * unregister 'numsnaps - numkeep' additional snapshots, repeating + * 'numiters' times. All the register/unregister calls are made in + * LIFO order. + * + * Returns the time spent, in milliseconds. + * + * The idea is to test the performance of ResourceOwnerRemember() + * and ReourceOwnerForget() operations, under different regimes. + * + * In the old implementation, if 'numsnaps' is small enough, all + * the entries fit in the resource owner's small array (it can + * hold 64 entries). + * + * In the new implementation, the array is much smaller, only 8 + * entries, but it's used together with the hash table so that + * we stay in the "array regime" as long as 'numsnaps - numkeep' + * is smaller than 8 entries. + * + * 'numiters' can be adjusted to adjust the overall runtime to be + * suitable long. + */ +Datum +snapshotbench_lifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + while (numregistered > numkeep) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + } + + while (numregistered > 0) + { + numregistered--; + UnregisterSnapshot(rs[numregistered]); + } + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; + + +/* + * Same, but do the register/unregister operations in + * FIFO order. + */ +Datum +snapshotbench_fifo(PG_FUNCTION_ARGS) +{ + int numkeep = PG_GETARG_INT32(0); + int numsnaps = PG_GETARG_INT32(1); + int numiters = PG_GETARG_INT32(2); + int i, + j; + instr_time start, + duration; + Snapshot lsnap; + Snapshot *rs; + int numregistered = 0; + + rs = palloc(Max(numsnaps, numkeep) * sizeof(Snapshot)); + + lsnap = GetLatestSnapshot(); + + PG_SETMASK(&BlockSig); + INSTR_TIME_SET_CURRENT(start); + + while (numregistered < numkeep) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (i = 0 ; i < numiters; i++) + { + while (numregistered < numsnaps) + { + rs[numregistered] = RegisterSnapshot(lsnap); + numregistered++; + } + + for (j = numkeep; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + } + + for (j = 0; j < numregistered; j++) + UnregisterSnapshot(rs[j]); + numregistered = numkeep; + + INSTR_TIME_SET_CURRENT(duration); + INSTR_TIME_SUBTRACT(duration, start); + PG_SETMASK(&UnBlockSig); + + PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(duration)); +}; diff --git a/contrib/resownerbench/resownerbench.control b/contrib/resownerbench/resownerbench.control new file mode 100644 index 00000000000..ada88b8eed8 --- /dev/null +++ b/contrib/resownerbench/resownerbench.control @@ -0,0 +1,6 @@ +# resownerbench + +comment = 'benchmark for ResourceOwners' +default_version = '1.0' +module_pathname = '$libdir/resownerbench' +relocatable = true diff --git a/contrib/resownerbench/snaptest.sql b/contrib/resownerbench/snaptest.sql new file mode 100644 index 00000000000..18c54e13fc9 --- /dev/null +++ b/contrib/resownerbench/snaptest.sql @@ -0,0 +1,37 @@ +-- +-- Performance test RegisterSnapshot/UnregisterSnapshot. +-- +select numkeep, numsnaps, + -- numiters, + -- round(lifo_time_ms) as lifo_total_time_ms, + -- round(fifo_time_ms) as fifo_total_time_ms, + round((lifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as lifo_time_ns, + round((fifo_time_ms::numeric / (numkeep + (numsnaps - numkeep) * numiters)) * 1000000, 1) as fifo_time_ns +from +(values (0, 1, 10000000), + (0, 5, 2000000), + (0, 10, 1000000), + (0, 60, 100000), + (0, 70, 100000), + (0, 100, 100000), + (0, 1000, 10000), + (0, 10000, 1000), + +-- These tests keep 9 snapshots registered across the iterations. That +-- exceeds the size of the little array in the patch, so this exercises +-- the hash lookups. Without the patch, these still fit in the array +-- (it's 64 entries without the patch) + (9, 10, 10000000), + (9, 100, 100000), + (9, 1000, 10000), + (9, 10000, 1000), + +-- These exceed the 64 entry array even without the patch, so these fall +-- in the hash table regime with and without the patch. + (65, 70, 1000000), + (65, 100, 100000), + (65, 1000, 10000), + (65, 10000, 1000) +) AS params (numkeep, numsnaps, numiters), +lateral snapshotbench_lifo(numkeep, numsnaps, numiters) as lifo_time_ms, +lateral snapshotbench_fifo(numkeep, numsnaps, numiters) as fifo_time_ms; -- 2.29.2 --------------1104342304EC6341F5D7C60C-- ^ permalink raw reply [nested|flat] 43+ messages in thread
* Re: Code checks for App Devs, using new options for transaction behavior @ 2023-03-23 20:05 Greg Stark <[email protected]> 0 siblings, 0 replies; 43+ messages in thread From: Greg Stark @ 2023-03-23 20:05 UTC (permalink / raw) To: Simon Riggs <[email protected]>; +Cc: pgsql-hackers On Thu, 27 Oct 2022 at 07:10, Simon Riggs <[email protected]> wrote: > > In the past, developers have wondered how we can provide "--dry-run" > functionality That would be an awesome functionality, indeed. I have concerns of how feasible it is in general but I think providing features to allow developers to build it for their use cases is a good approach. The corner cases that might not be possible in general might be tractable developers willing to constrain their development environment or use information available outside Postgres. But... I have concerns about some of the design here. > * psql --parse-only > Checks the syntax of all SQL in a script, but without actually > executing it. This is very important in the early stages of complex > migrations because we need to see if the code would generate syntax > errors before we attempt to execute it. When there are many > dependencies between objects, actual execution fails very quickly if > we run in a single transaction, yet running outside of a transaction > can leave a difficult cleanup task. Fixing errors iteratively is > difficult when there are long chains of dependencies between objects, > since there is no easy way to predict how long it will take to make > everything work unless you understand how many syntax errors exist in > the script. > 001_psql_parse_only.v1.patch This effectively enables \gdesc mode for every query. It needs docs explaining what's actually going to happen and how to use it because that wasn't super obvious to me even after reading the patch. I'm not sure reusing DescribeQuery() and then returning early is the best idea. But more importantly it's only going to handle the simplest scripts that don't do DDL that further statements will depend on. That at least needs to be documented. > * nested transactions = off (default) | all | on > Handle nested BEGIN/COMMIT, which can cause chaos on failure. This is > an important part of guaranteeing that everything that gets executed > is part of a single atomic transaction, which can then be rolled back > - this is a pre-requisite for the last feature. > 002_nested_xacts.v7.patch > The default behavior is unchanged (off) > Setting "all" treats nested BEGIN/COMMIT as subtransactions, allowing > some parts to fail without rolling back the outer transaction. > Setting "outer" flattens nested BEGIN/COMMIT into one single outer > transaction, so that any failure rolls back the entire transaction. I think we've been burned pretty badly by GUCs that control SQL semantics before. I think there was discussion at the time nested transactions went in and there must have been a reason we did SAVEPOINT rather than make nested BEGINs do things like this. But regardless if we do want to change what nested BEGINs do I think we have to decide what behaviour we want, think about the backwards compatibility impacts, and make the change. We can't make it just for some people some of the time based on a GUC. Doing that makes it impossible to write scripts that work consistently. I'm not clear what happens if you have this feature enabled and *also* use SAVEPOINTs... You say this is a prerequisite for 003 and I see how they're related though I don't immediately see why it should be necessary to change nested BEGIN behaviour to make that work. > * rollback_on_commit = off (default) | on > Force transactions to fail their final commit, ensuring that no > lasting change is made when a script is tested. i.e. accept COMMIT, > but do rollback instead. > 003_rollback_on_commit.v1.patch I suppose technically this is also a "semantics controlled by a GUC" but I guess it's safe since you would only set this when you want this debugging environment and then you really do want it to be global. I'm not sure it's super safe though. Like, dblink connections can break it, what happens if it gets turned off midway through a transaction? I wonder if this should be handled by the client itself the way autocommit is. Like have an "autocommit" mode of "autorollback" instead. That would mean having to add it to every client library of course but then perhaps it would be able to change client behaviour in ways that make sense at the same time. -- greg ^ permalink raw reply [nested|flat] 43+ messages in thread
end of thread, other threads:[~2023-03-23 20:05 UTC | newest] Thread overview: 43+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2020-11-11 22:40 [PATCH 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH v2 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH v2 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH v2 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH v2 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH v2 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH v2 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH v2 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH v2 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH v2 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH v2 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH v2 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH v2 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH v2 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH v2 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH v2 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH v2 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH v2 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH v2 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH v2 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH v2 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH 1/1] resownerbench Heikki Linnakangas <[email protected]> 2020-11-11 22:40 [PATCH v2 1/1] resownerbench Heikki Linnakangas <[email protected]> 2023-03-23 20:05 Re: Code checks for App Devs, using new options for transaction behavior Greg Stark <[email protected]>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox