summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeikki Linnakangas2016-08-22 16:23:34 +0000
committerHeikki Linnakangas2016-08-22 18:21:58 +0000
commitd6176e87030f39de91182c05ecab2b37b1bd688c (patch)
treee06b1eeb680102ef39fc5d212edde3a7f71159e1
parent295dee2321acea93f4f1e189b3c84e4fec7cdbb1 (diff)
Add a test modulecsn5
-rw-r--r--src/test/modules/mvcctorture/Makefile18
-rw-r--r--src/test/modules/mvcctorture/README25
-rw-r--r--src/test/modules/mvcctorture/mvcctorture--1.0.sql9
-rw-r--r--src/test/modules/mvcctorture/mvcctorture.c129
-rw-r--r--src/test/modules/mvcctorture/mvcctorture.control5
5 files changed, 186 insertions, 0 deletions
diff --git a/src/test/modules/mvcctorture/Makefile b/src/test/modules/mvcctorture/Makefile
new file mode 100644
index 0000000000..cc4ebc838a
--- /dev/null
+++ b/src/test/modules/mvcctorture/Makefile
@@ -0,0 +1,18 @@
+# src/test/modules/mvcctorture/Makefile
+
+MODULE_big = mvcctorture
+OBJS = mvcctorture.o
+
+EXTENSION = mvcctorture
+DATA = mvcctorture--1.0.sql
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = src/test/modules/mvcctorture
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/src/test/modules/mvcctorture/README b/src/test/modules/mvcctorture/README
new file mode 100644
index 0000000000..915b00129a
--- /dev/null
+++ b/src/test/modules/mvcctorture/README
@@ -0,0 +1,25 @@
+A litte helper module for testing MVCC performance.
+
+The populate_mvcc_test_table function can be used to create a test table,
+with given number of rows. Each row in the table is stamped with a different
+xmin, and XMIN_COMMITTED hint bit can be set or not. Furthermore, the
+xmins values are shuffled, to defeat caching in transam.c and clog.c as badly
+as possible.
+
+The test table is always called "mvcc_test_table". You'll have to drop it
+yourself between tests.
+
+For example:
+
+-- Create a test table with 10 million rows, without setting hint bits
+select populate_mvcc_test_table(10000000, false);
+
+-- See how long it takes to scan it
+\timing
+select count(*) from mvcc_test_table;
+
+
+
+If you do the above, but have another psql session open, in a transaction
+that's done some updates, i.e. is holding backthe xmin horizon, you will
+see the worst-case performance of the CSN patch.
diff --git a/src/test/modules/mvcctorture/mvcctorture--1.0.sql b/src/test/modules/mvcctorture/mvcctorture--1.0.sql
new file mode 100644
index 0000000000..652a6a3f39
--- /dev/null
+++ b/src/test/modules/mvcctorture/mvcctorture--1.0.sql
@@ -0,0 +1,9 @@
+/* src/test/modules/mvcctorture/mvcctorture--1.0.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION mvcctorture" to load this file. \quit
+
+CREATE FUNCTION populate_mvcc_test_table(int4, bool)
+RETURNS void
+AS 'MODULE_PATHNAME', 'populate_mvcc_test_table'
+LANGUAGE C STRICT;
diff --git a/src/test/modules/mvcctorture/mvcctorture.c b/src/test/modules/mvcctorture/mvcctorture.c
new file mode 100644
index 0000000000..a89a2e6e96
--- /dev/null
+++ b/src/test/modules/mvcctorture/mvcctorture.c
@@ -0,0 +1,129 @@
+/*-------------------------------------------------------------------------
+ *
+ * mvctorture.c
+ *
+ * Copyright (c) 2012, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/test/modules/mvcctorture.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "access/heapam.h"
+#include "access/hio.h"
+#include "access/htup_details.h"
+#include "access/transam.h"
+#include "access/xact.h"
+#include "access/visibilitymap.h"
+#include "catalog/pg_am.h"
+#include "executor/spi.h"
+#include "funcapi.h"
+#include "nodes/makefuncs.h"
+#include "storage/bufmgr.h"
+#include "utils/rel.h"
+
+PG_MODULE_MAGIC;
+
+PG_FUNCTION_INFO_V1(populate_mvcc_test_table);
+
+Datum
+populate_mvcc_test_table(PG_FUNCTION_ARGS)
+{
+ uint32 nrows = PG_GETARG_UINT32(0);
+ bool set_xmin_committed = PG_GETARG_BOOL(1);
+ RangeVar *rv;
+ Relation rel;
+ Datum values[1];
+ bool isnull[1];
+ HeapTuple tup;
+ TransactionId *xids;
+ int ret;
+ int i;
+ Buffer buffer;
+ Buffer vmbuffer = InvalidBuffer;
+
+ /* Connect to SPI manager */
+ if ((ret = SPI_connect()) < 0)
+ /* internal error */
+ elog(ERROR, "populate_mvcc_test_table: SPI_connect returned %d", ret);
+
+ SPI_execute("CREATE TABLE mvcc_test_table(i int4)", false, 0);
+
+ SPI_finish();
+
+ /* Generate a different XID for each tuple */
+ xids = (TransactionId *) palloc0(nrows * sizeof(TransactionId));
+ for (i = 0; i < nrows; i++)
+ {
+ BeginInternalSubTransaction(NULL);
+ xids[i] = GetCurrentTransactionId();
+ ReleaseCurrentSubTransaction();
+ }
+
+ rv = makeRangeVar(NULL, "mvcc_test_table", -1);
+
+ rel = heap_openrv(rv, RowExclusiveLock);
+
+ /* shuffle */
+ for (i = 0; i < nrows - 1; i++)
+ {
+ int x = i + (random() % (nrows - i));
+ TransactionId tmp;
+
+ tmp = xids[i];
+ xids[i] = xids[x];
+ xids[x] = tmp;
+ }
+
+ for (i = 0; i < nrows; i++)
+ {
+ values[0] = Int32GetDatum(i);
+ isnull[0] = false;
+
+ tup = heap_form_tuple(RelationGetDescr(rel), values, isnull);
+
+ /* Fill the header fields, like heap_prepare_insert does */
+ tup->t_data->t_infomask &= ~(HEAP_XACT_MASK);
+ tup->t_data->t_infomask2 &= ~(HEAP2_XACT_MASK);
+ tup->t_data->t_infomask |= HEAP_XMAX_INVALID;
+ if (set_xmin_committed)
+ tup->t_data->t_infomask |= HEAP_XMIN_COMMITTED;
+ HeapTupleHeaderSetXmin(tup->t_data, xids[i]);
+ HeapTupleHeaderSetCmin(tup->t_data, 1);
+ HeapTupleHeaderSetXmax(tup->t_data, 0); /* for cleanliness */
+ tup->t_tableOid = RelationGetRelid(rel);
+
+ heap_freetuple(tup);
+
+ /*
+ * Find buffer to insert this tuple into. If the page is all visible,
+ * this will also pin the requisite visibility map page.
+ */
+ buffer = RelationGetBufferForTuple(rel, tup->t_len,
+ InvalidBuffer,
+ 0, NULL,
+ &vmbuffer, NULL);
+ RelationPutHeapTuple(rel, buffer, tup, false);
+
+ if (PageIsAllVisible(BufferGetPage(buffer)))
+ {
+ PageClearAllVisible(BufferGetPage(buffer));
+ visibilitymap_clear(rel,
+ ItemPointerGetBlockNumber(&(tup->t_self)),
+ vmbuffer, VISIBILITYMAP_VALID_BITS);
+ }
+
+ MarkBufferDirty(buffer);
+ UnlockReleaseBuffer(buffer);
+ }
+
+ if (vmbuffer != InvalidBuffer)
+ ReleaseBuffer(vmbuffer);
+
+ heap_close(rel, NoLock);
+
+ PG_RETURN_VOID();
+}
diff --git a/src/test/modules/mvcctorture/mvcctorture.control b/src/test/modules/mvcctorture/mvcctorture.control
new file mode 100644
index 0000000000..1b5feb95a7
--- /dev/null
+++ b/src/test/modules/mvcctorture/mvcctorture.control
@@ -0,0 +1,5 @@
+# mvcctorture extension
+comment = 'populate a table with a mix of different XIDs'
+default_version = '1.0'
+module_pathname = '$libdir/mvcctorture'
+relocatable = true