From 326d3dc3d636e3b3b03aa5a385ccd12a3bad581a Mon Sep 17 00:00:00 2001 From: Tomas Vondra Date: Sat, 31 Jul 2021 22:55:36 +0200 Subject: [PATCH 1/4] generation bench --- contrib/generation_bench/.gitignore | 4 + contrib/generation_bench/Makefile | 21 + contrib/generation_bench/bench.sql | 88 ++++ .../generation_bench--1.0.sql | 16 + contrib/generation_bench/generation_bench.c | 449 ++++++++++++++++++ .../generation_bench/generation_bench.control | 4 + 6 files changed, 582 insertions(+) create mode 100644 contrib/generation_bench/.gitignore create mode 100644 contrib/generation_bench/Makefile create mode 100644 contrib/generation_bench/bench.sql create mode 100644 contrib/generation_bench/generation_bench--1.0.sql create mode 100644 contrib/generation_bench/generation_bench.c create mode 100644 contrib/generation_bench/generation_bench.control diff --git a/contrib/generation_bench/.gitignore b/contrib/generation_bench/.gitignore new file mode 100644 index 0000000000..5dcb3ff972 --- /dev/null +++ b/contrib/generation_bench/.gitignore @@ -0,0 +1,4 @@ +# Generated subdirectories +/log/ +/results/ +/tmp_check/ diff --git a/contrib/generation_bench/Makefile b/contrib/generation_bench/Makefile new file mode 100644 index 0000000000..0fee5b84db --- /dev/null +++ b/contrib/generation_bench/Makefile @@ -0,0 +1,21 @@ +# contrib/generation_bench/Makefile + +MODULE_big = generation_bench +OBJS = generation_bench.o + +EXTENSION = generation_bench +DATA = generation_bench--1.0.sql +PGFILEDESC = "generation_bench - slab context benchmarking functions" + +REGRESS = generation_bench + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = contrib/generation_bench +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif diff --git a/contrib/generation_bench/bench.sql b/contrib/generation_bench/bench.sql new file mode 100644 index 0000000000..05f065ace5 --- /dev/null +++ b/contrib/generation_bench/bench.sql @@ -0,0 +1,88 @@ +CREATE EXTENSION generation_bench; + +\o fifo-no-loops.data +select 1 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_fifo(1000000, block_size, chunk_size, 2*chunk_size, 0, 0, 0) x; +select 2 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_fifo(1000000, block_size, chunk_size, 2*chunk_size, 0, 0, 0) x; +select 3 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_fifo(1000000, block_size, chunk_size, 2*chunk_size, 0, 0, 0) x; +select 4 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_fifo(1000000, block_size, chunk_size, 2*chunk_size, 0, 0, 0) x; +select 5 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_fifo(1000000, block_size, chunk_size, 2*chunk_size, 0, 0, 0) x; + +\o lifo-no-loops.data +select 1 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_lifo(1000000, block_size, chunk_size, 2*chunk_size, 0, 0, 0) x; +select 2 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_lifo(1000000, block_size, chunk_size, 2*chunk_size, 0, 0, 0) x; +select 3 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_lifo(1000000, block_size, chunk_size, 2*chunk_size, 0, 0, 0) x; +select 4 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_lifo(1000000, block_size, chunk_size, 2*chunk_size, 0, 0, 0) x; +select 5 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_lifo(1000000, block_size, chunk_size, 2*chunk_size, 0, 0, 0) x; + +\o random-no-loops.data +select 1 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_random(1000000, block_size, chunk_size, 2*chunk_size, 0, 0, 0) x; +select 2 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_random(1000000, block_size, chunk_size, 2*chunk_size, 0, 0, 0) x; +select 3 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_random(1000000, block_size, chunk_size, 2*chunk_size, 0, 0, 0) x; +select 4 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_random(1000000, block_size, chunk_size, 2*chunk_size, 0, 0, 0) x; +select 5 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_random(1000000, block_size, chunk_size, 2*chunk_size, 0, 0, 0) x; + + +\o fifo-increase.data +select 1 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_fifo(1000000, block_size, chunk_size, 2*chunk_size, 100, 10000, 15000) x; +select 2 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_fifo(1000000, block_size, chunk_size, 2*chunk_size, 100, 10000, 15000) x; +select 3 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_fifo(1000000, block_size, chunk_size, 2*chunk_size, 100, 10000, 15000) x; +select 4 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_fifo(1000000, block_size, chunk_size, 2*chunk_size, 100, 10000, 15000) x; +select 5 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_fifo(1000000, block_size, chunk_size, 2*chunk_size, 100, 10000, 15000) x; + +\o lifo-increase.data +select 1 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_lifo(1000000, block_size, chunk_size, 2*chunk_size, 100, 10000, 15000) x; +select 2 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_lifo(1000000, block_size, chunk_size, 2*chunk_size, 100, 10000, 15000) x; +select 3 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_lifo(1000000, block_size, chunk_size, 2*chunk_size, 100, 10000, 15000) x; +select 4 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_lifo(1000000, block_size, chunk_size, 2*chunk_size, 100, 10000, 15000) x; +select 5 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_lifo(1000000, block_size, chunk_size, 2*chunk_size, 100, 10000, 15000) x; + +\o random-increase.data +select 1 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_random(1000000, block_size, chunk_size, 2*chunk_size, 100, 1000, 1500) x; +select 2 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_random(1000000, block_size, chunk_size, 2*chunk_size, 100, 1000, 1500) x; +select 3 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_random(1000000, block_size, chunk_size, 2*chunk_size, 100, 1000, 1500) x; +select 4 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_random(1000000, block_size, chunk_size, 2*chunk_size, 100, 1000, 1500) x; +select 5 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_random(1000000, block_size, chunk_size, 2*chunk_size, 100, 1000, 1500) x; + + +\o fifo-decrease.data +select 1 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_fifo(1000000, block_size, chunk_size, 2*chunk_size, 100, 10000, 5000) x; +select 2 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_fifo(1000000, block_size, chunk_size, 2*chunk_size, 100, 10000, 5000) x; +select 3 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_fifo(1000000, block_size, chunk_size, 2*chunk_size, 100, 10000, 5000) x; +select 4 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_fifo(1000000, block_size, chunk_size, 2*chunk_size, 100, 10000, 5000) x; +select 5 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_fifo(1000000, block_size, chunk_size, 2*chunk_size, 100, 10000, 5000) x; + +\o lifo-decrease.data +select 1 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_lifo(1000000, block_size, chunk_size, 2*chunk_size, 100, 10000, 5000) x; +select 2 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_lifo(1000000, block_size, chunk_size, 2*chunk_size, 100, 10000, 5000) x; +select 3 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_lifo(1000000, block_size, chunk_size, 2*chunk_size, 100, 10000, 5000) x; +select 4 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_lifo(1000000, block_size, chunk_size, 2*chunk_size, 100, 10000, 5000) x; +select 5 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_lifo(1000000, block_size, chunk_size, 2*chunk_size, 100, 10000, 5000) x; + +\o random-decrease.data +select 1 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_random(1000000, block_size, chunk_size, 2*chunk_size, 100, 1000, 500) x; +select 2 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_random(1000000, block_size, chunk_size, 2*chunk_size, 100, 1000, 500) x; +select 3 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_random(1000000, block_size, chunk_size, 2*chunk_size, 100, 1000, 500) x; +select 4 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_random(1000000, block_size, chunk_size, 2*chunk_size, 100, 1000, 500) x; +select 5 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_random(1000000, block_size, chunk_size, 2*chunk_size, 100, 1000, 500) x; + + +\o fifo-cycle.data +select 1 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_fifo(1000, block_size, chunk_size, 2*chunk_size, 1000, 1000, 1000) x; +select 2 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_fifo(1000, block_size, chunk_size, 2*chunk_size, 1000, 1000, 1000) x; +select 3 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_fifo(1000, block_size, chunk_size, 2*chunk_size, 1000, 1000, 1000) x; +select 4 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_fifo(1000, block_size, chunk_size, 2*chunk_size, 1000, 1000, 1000) x; +select 5 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_fifo(1000, block_size, chunk_size, 2*chunk_size, 1000, 1000, 1000) x; + +\o lifo-cycle.data +select 1 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_lifo(1000, block_size, chunk_size, 2*chunk_size, 1000, 1000, 1000) x; +select 2 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_lifo(1000, block_size, chunk_size, 2*chunk_size, 1000, 1000, 1000) x; +select 3 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_lifo(1000, block_size, chunk_size, 2*chunk_size, 1000, 1000, 1000) x; +select 4 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_lifo(1000, block_size, chunk_size, 2*chunk_size, 1000, 1000, 1000) x; +select 5 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_lifo(1000, block_size, chunk_size, 2*chunk_size, 1000, 1000, 1000) x; + +\o random-cycle.data +select 1 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_random(1000, block_size, chunk_size, 2*chunk_size, 1000, 1000, 1000) x; +select 2 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_random(1000, block_size, chunk_size, 2*chunk_size, 1000, 1000, 1000) x; +select 3 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_random(1000, block_size, chunk_size, 2*chunk_size, 1000, 1000, 1000) x; +select 4 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_random(1000, block_size, chunk_size, 2*chunk_size, 1000, 1000, 1000) x; +select 5 as run, block_size, chunk_size, 2*chunk_size, 1000000 * chunk_size, x.* from generate_series(32,512,32) a(chunk_size), (values (1024), (2048), (4096), (8192), (16384), (32768)) AS b(block_size), lateral generation_bench_random(1000, block_size, chunk_size, 2*chunk_size, 1000, 1000, 1000) x; diff --git a/contrib/generation_bench/generation_bench--1.0.sql b/contrib/generation_bench/generation_bench--1.0.sql new file mode 100644 index 0000000000..5f7c46eef2 --- /dev/null +++ b/contrib/generation_bench/generation_bench--1.0.sql @@ -0,0 +1,16 @@ +/* generation_bench--1.0.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION generation_bench" to load this file. \quit + +CREATE FUNCTION generation_bench_random(nallocs bigint, block_size bigint, min_alloc_size bigint, max_alloc_size bigint, loops int, free_cnt int, alloc_cnt int, out mem_allocated bigint, out alloc_ms bigint, out free_ms bigint) +AS 'MODULE_PATHNAME', 'generation_bench_random' +LANGUAGE C VOLATILE STRICT; + +CREATE FUNCTION generation_bench_fifo(nallocs bigint, block_size bigint, min_alloc_size bigint, max_alloc_size bigint, loops int, free_cnt int, alloc_cnt int, out mem_allocated bigint, out alloc_ms bigint, out free_ms bigint) +AS 'MODULE_PATHNAME', 'generation_bench_fifo' +LANGUAGE C VOLATILE STRICT; + +CREATE FUNCTION generation_bench_lifo(nallocs bigint, block_size bigint, min_alloc_size bigint, max_alloc_size bigint, loops int, free_cnt int, alloc_cnt int, out mem_allocated bigint, out alloc_ms bigint, out free_ms bigint) +AS 'MODULE_PATHNAME', 'generation_bench_lifo' +LANGUAGE C VOLATILE STRICT; diff --git a/contrib/generation_bench/generation_bench.c b/contrib/generation_bench/generation_bench.c new file mode 100644 index 0000000000..f86aaaa041 --- /dev/null +++ b/contrib/generation_bench/generation_bench.c @@ -0,0 +1,449 @@ +/*------------------------------------------------------------------------- + * + * generation_bench.c + * + * helper functions to benchmark generation context with different workloads + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include +#include + +#include "funcapi.h" +#include "miscadmin.h" + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(generation_bench_random); +PG_FUNCTION_INFO_V1(generation_bench_fifo); +PG_FUNCTION_INFO_V1(generation_bench_lifo); + +typedef struct Chunk { + int random; + void *ptr; +} Chunk; + +static int +chunk_index_cmp(const void *a, const void *b) +{ + Chunk *ca = (Chunk *) a; + Chunk *cb = (Chunk *) b; + + if (ca->random < cb->random) + return -1; + else if (ca->random > cb->random) + return 1; + + return 0; +} + +#ifdef RDTSC +// optional wrapper if you don't want to just use __rdtsc() everywhere +static inline +unsigned long long read_time(void) +{ + // _mm_lfence(); // optionally wait for earlier insns to retire before reading the clock + return __rdtsc(); + // _mm_lfence(); // optionally block later instructions until rdtsc retires +} +#else +static inline +unsigned long long read_time(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + return (unsigned long long) tv.tv_sec * 1000000L + tv.tv_usec; +} +#endif + +Datum +generation_bench_random(PG_FUNCTION_ARGS) +{ + MemoryContext cxt, + oldcxt; + Chunk *chunks; + int64 i, j; + int64 nallocs = PG_GETARG_INT64(0); + int64 blockSize = PG_GETARG_INT64(1); + int64 minChunkSize = PG_GETARG_INT64(2); + int64 maxChunkSize = PG_GETARG_INT64(3); + + int nloops = PG_GETARG_INT32(4); + int free_cnt = PG_GETARG_INT32(5); + int alloc_cnt = PG_GETARG_INT32(6); + + unsigned long long start_time, + end_time; + + int64 alloc_time = 0, + free_time = 0; + int64 mem_allocated; + + TupleDesc tupdesc; + Datum result; + HeapTuple tuple; + Datum values[9]; + bool nulls[9]; + + int maxchunks; + + maxchunks = nallocs + nloops * Max(0, alloc_cnt - free_cnt); + + cxt = GenerationContextCreate(CurrentMemoryContext, "generation_bench", blockSize); + + chunks = (Chunk *) palloc(maxchunks * sizeof(Chunk)); + + /* allocate the chunks in random order */ + oldcxt = MemoryContextSwitchTo(cxt); + + start_time = read_time(); + + for (i = 0; i < nallocs; i++) + { + int chunkSize = minChunkSize + random() % (maxChunkSize - minChunkSize); + + chunks[i].ptr = palloc(chunkSize); + } + + end_time = read_time(); + + alloc_time += (end_time - start_time); + + MemoryContextSwitchTo(oldcxt); + + mem_allocated = MemoryContextMemAllocated(cxt, true); + + /* do the requested number of free/alloc loops */ + for (j = 0; j < nloops; j++) + { + CHECK_FOR_INTERRUPTS(); + + /* randomize the indexes */ + for (i = 0; i < nallocs; i++) + chunks[i].random = random(); + + qsort(chunks, nallocs, sizeof(Chunk), chunk_index_cmp); + + oldcxt = MemoryContextSwitchTo(cxt); + + start_time = read_time(); + + /* free the first free_cnt chunks */ + for (i = 0; i < Min(nallocs, free_cnt); i++) + pfree(chunks[i].ptr); + + end_time = read_time(); + + nallocs -= Min(nallocs, free_cnt); + + free_time += (end_time - start_time); + + memmove(chunks, &chunks[free_cnt], nallocs * sizeof(Chunk)); + + + /* allocate alloc_cnt chunks at the end */ + start_time = read_time(); + + /* free the first free_cnt chunks */ + for (i = 0; i < alloc_cnt; i++) + { + int chunkSize = minChunkSize + random() % (maxChunkSize - minChunkSize); + + chunks[nallocs + i].ptr = palloc(chunkSize); + } + + end_time = read_time(); + + nallocs += alloc_cnt; + + alloc_time += (end_time - start_time); + + MemoryContextSwitchTo(oldcxt); + + mem_allocated = Max(mem_allocated, MemoryContextMemAllocated(cxt, true)); + } + + /* release the chunks in random order */ + for (i = 0; i < nallocs; i++) + chunks[i].random = random(); + + qsort(chunks, nallocs, sizeof(Chunk), chunk_index_cmp); + + start_time = read_time(); + + for (i = 0; i < nallocs; i++) + pfree(chunks[i].ptr); + + end_time = read_time(); + + free_time += (end_time - start_time); + + /* Build a tuple descriptor for our result type */ + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + + values[0] = Int64GetDatum(mem_allocated); + values[1] = Int64GetDatum(alloc_time); + values[2] = Int64GetDatum(free_time); + + memset(nulls, 0, sizeof(nulls)); + + tuple = heap_form_tuple(tupdesc, values, nulls); + result = HeapTupleGetDatum(tuple); + + PG_RETURN_DATUM(result); +} + +Datum +generation_bench_fifo(PG_FUNCTION_ARGS) +{ + MemoryContext cxt, + oldcxt; + Chunk *chunks; + int64 i, j; + int64 nallocs = PG_GETARG_INT64(0); + int64 blockSize = PG_GETARG_INT64(1); + int64 minChunkSize = PG_GETARG_INT64(2); + int64 maxChunkSize = PG_GETARG_INT64(3); + + int nloops = PG_GETARG_INT32(4); + int free_cnt = PG_GETARG_INT32(5); + int alloc_cnt = PG_GETARG_INT32(6); + + unsigned long long start_time, + end_time; + + int64 alloc_time = 0, + free_time = 0; + int64 mem_allocated; + + TupleDesc tupdesc; + Datum result; + HeapTuple tuple; + Datum values[9]; + bool nulls[9]; + + int maxchunks; + + maxchunks = nallocs + nloops * Max(0, alloc_cnt - free_cnt); + + cxt = GenerationContextCreate(CurrentMemoryContext, "generation_bench", blockSize); + + chunks = (Chunk *) palloc(maxchunks * sizeof(Chunk)); + + oldcxt = MemoryContextSwitchTo(cxt); + + start_time = read_time(); + + for (i = 0; i < nallocs; i++) + { + int chunkSize = minChunkSize + random() % (maxChunkSize - minChunkSize); + + chunks[i].ptr = palloc(chunkSize); + } + + end_time = read_time(); + + alloc_time += (end_time - start_time); + + MemoryContextSwitchTo(oldcxt); + + mem_allocated = MemoryContextMemAllocated(cxt, true); + + + /* do the requested number of free/alloc loops */ + for (j = 0; j < nloops; j++) + { + CHECK_FOR_INTERRUPTS(); + + oldcxt = MemoryContextSwitchTo(cxt); + + start_time = read_time(); + + /* free the first free_cnt chunks */ + for (i = 0; i < Min(nallocs, free_cnt); i++) + pfree(chunks[i].ptr); + + end_time = read_time(); + + nallocs -= Min(nallocs, free_cnt); + + free_time += (end_time - start_time); + + memmove(chunks, &chunks[free_cnt], nallocs * sizeof(Chunk)); + + /* allocate alloc_cnt chunks at the end */ + start_time = read_time(); + + /* free the first free_cnt chunks */ + for (i = 0; i < alloc_cnt; i++) + { + int chunkSize = minChunkSize + random() % (maxChunkSize - minChunkSize); + + chunks[nallocs + i].ptr = palloc(chunkSize); + } + + end_time = read_time(); + + nallocs += alloc_cnt; + + alloc_time += (end_time - start_time); + + MemoryContextSwitchTo(oldcxt); + + mem_allocated = Max(mem_allocated, MemoryContextMemAllocated(cxt, true)); + } + + start_time = read_time(); + + for (i = 0; i < nallocs; i++) + pfree(chunks[i].ptr); + + end_time = read_time(); + + free_time += (end_time - start_time); + + /* Build a tuple descriptor for our result type */ + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + + values[0] = Int64GetDatum(mem_allocated); + values[1] = Int64GetDatum(alloc_time); + values[2] = Int64GetDatum(free_time); + + memset(nulls, 0, sizeof(nulls)); + + tuple = heap_form_tuple(tupdesc, values, nulls); + result = HeapTupleGetDatum(tuple); + + PG_RETURN_DATUM(result); +} + +Datum +generation_bench_lifo(PG_FUNCTION_ARGS) +{ + MemoryContext cxt, + oldcxt; + Chunk *chunks; + int64 i, j; + int64 nallocs = PG_GETARG_INT64(0); + int64 blockSize = PG_GETARG_INT64(1); + int64 minChunkSize = PG_GETARG_INT64(2); + int64 maxChunkSize = PG_GETARG_INT64(3); + + int nloops = PG_GETARG_INT32(4); + int free_cnt = PG_GETARG_INT32(5); + int alloc_cnt = PG_GETARG_INT32(6); + + unsigned long long start_time, + end_time; + + int64 alloc_time = 0, + free_time = 0; + int64 mem_allocated; + + TupleDesc tupdesc; + Datum result; + HeapTuple tuple; + Datum values[9]; + bool nulls[9]; + + int maxchunks; + + maxchunks = nallocs + nloops * Max(0, alloc_cnt - free_cnt); + + cxt = GenerationContextCreate(CurrentMemoryContext, "generation_bench", blockSize); + + chunks = (Chunk *) palloc(maxchunks * sizeof(Chunk)); + + oldcxt = MemoryContextSwitchTo(cxt); + + /* palloc benchmark */ + start_time = read_time(); + + for (i = 0; i < nallocs; i++) + { + int chunkSize = minChunkSize + random() % (maxChunkSize - minChunkSize); + + chunks[i].ptr = palloc(chunkSize); + } + + end_time = read_time(); + + alloc_time += (end_time - start_time); + + MemoryContextSwitchTo(oldcxt); + + mem_allocated = MemoryContextMemAllocated(cxt, true); + + + /* do the requested number of free/alloc loops */ + for (j = 0; j < nloops; j++) + { + CHECK_FOR_INTERRUPTS(); + + oldcxt = MemoryContextSwitchTo(cxt); + + start_time = read_time(); + + /* free the first free_cnt chunks */ + for (i = 1; i <= Min(nallocs, free_cnt); i++) + pfree(chunks[nallocs - i].ptr); + + end_time = read_time(); + + nallocs -= Min(nallocs, free_cnt); + + free_time += (end_time - start_time); + + /* allocate alloc_cnt chunks at the end */ + start_time = read_time(); + + /* free the first free_cnt chunks */ + for (i = 0; i < alloc_cnt; i++) + { + int chunkSize = minChunkSize + random() % (maxChunkSize - minChunkSize); + + chunks[nallocs + i].ptr = palloc(chunkSize); + } + + end_time = read_time(); + + nallocs += alloc_cnt; + + alloc_time += (end_time - start_time); + + MemoryContextSwitchTo(oldcxt); + + mem_allocated = Max(mem_allocated, MemoryContextMemAllocated(cxt, true)); + } + + + start_time = read_time(); + + for (i = (nallocs - 1); i >= 0; i--) + pfree(chunks[i].ptr); + + end_time = read_time(); + + free_time += (end_time - start_time); + + /* Build a tuple descriptor for our result type */ + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); + + values[0] = Int64GetDatum(mem_allocated); + values[1] = Int64GetDatum(alloc_time); + values[2] = Int64GetDatum(free_time); + + memset(nulls, 0, sizeof(nulls)); + + tuple = heap_form_tuple(tupdesc, values, nulls); + result = HeapTupleGetDatum(tuple); + + MemoryContextDelete(cxt); + + PG_RETURN_DATUM(result); +} diff --git a/contrib/generation_bench/generation_bench.control b/contrib/generation_bench/generation_bench.control new file mode 100644 index 0000000000..8c81e22e6b --- /dev/null +++ b/contrib/generation_bench/generation_bench.control @@ -0,0 +1,4 @@ +# generation_bench extension +comment = 'functions for benchmarking generation context' +default_version = '1.0' +module_pathname = '$libdir/generation_bench' -- 2.31.1