v11-0005-Add-benchmark-for-hashing-C-strings.patch
application/x-patch
Filename: v11-0005-Add-benchmark-for-hashing-C-strings.patch
Type: application/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v11-0005
Subject: Add benchmark for hashing C strings
| File | + | − |
|---|---|---|
| contrib/bench_hash/aligned_keywords.h | 991 | 0 |
| contrib/bench_hash/bench_hash--1.0.sql | 21 | 0 |
| contrib/bench_hash/bench_hash.c | 103 | 0 |
| contrib/bench_hash/bench_hash.control | 5 | 0 |
| contrib/bench_hash/Makefile | 23 | 0 |
| contrib/bench_hash/meson.build | 19 | 0 |
| contrib/meson.build | 1 | 0 |
From 778e3bdfc761dace149cd6c136e4c2847f793c61 Mon Sep 17 00:00:00 2001
From: John Naylor <john.naylor@postgresql.org>
Date: Sun, 24 Dec 2023 09:46:44 +0700
Subject: [PATCH v11 5/8] Add benchmark for hashing C strings
---
contrib/bench_hash/Makefile | 23 +
contrib/bench_hash/aligned_keywords.h | 991 +++++++++++++++++++++++++
contrib/bench_hash/bench_hash--1.0.sql | 21 +
contrib/bench_hash/bench_hash.c | 103 +++
contrib/bench_hash/bench_hash.control | 5 +
contrib/bench_hash/meson.build | 19 +
contrib/meson.build | 1 +
7 files changed, 1163 insertions(+)
create mode 100644 contrib/bench_hash/Makefile
create mode 100644 contrib/bench_hash/aligned_keywords.h
create mode 100644 contrib/bench_hash/bench_hash--1.0.sql
create mode 100644 contrib/bench_hash/bench_hash.c
create mode 100644 contrib/bench_hash/bench_hash.control
create mode 100644 contrib/bench_hash/meson.build
diff --git a/contrib/bench_hash/Makefile b/contrib/bench_hash/Makefile
new file mode 100644
index 0000000000..5327080376
--- /dev/null
+++ b/contrib/bench_hash/Makefile
@@ -0,0 +1,23 @@
+# src/test/modules/test_parser/Makefile
+
+MODULE_big = test_parser
+OBJS = \
+ $(WIN32RES) \
+ test_parser.o
+PGFILEDESC = "test_parser - example of a custom parser for full-text search"
+
+EXTENSION = test_parser
+DATA = test_parser--1.0.sql
+
+REGRESS = test_parser
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = src/test/modules/test_parser
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/contrib/bench_hash/aligned_keywords.h b/contrib/bench_hash/aligned_keywords.h
new file mode 100644
index 0000000000..c2bd67c856
--- /dev/null
+++ b/contrib/bench_hash/aligned_keywords.h
@@ -0,0 +1,991 @@
+/* created by copying from kwlist_d.h with this patch:
+
+--- a/src/tools/gen_keywordlist.pl
++++ b/src/tools/gen_keywordlist.pl
+@@ -97,7 +97,9 @@ while (<$kif>)
+ {
+ if (/^PG_KEYWORD\("(\w+)"/)
+ {
+- push @keywords, $1;
++ my $len = length($1) + 1;
++ my $aligned = $1 . "\\0" . "_" x ( ($len % 8) == 0 ? 0 : (8-($len % 8)) );
++ push @keywords, $aligned;
+ }
+ }
+
+@@ -127,7 +129,7 @@ for my $i (0 .. $#keywords - 1)
+ # Emit the string containing all the keywords.
+
+ printf $kwdef qq|static const char %s_kw_string[] =\n\t"|, $varname;
+-print $kwdef join qq|\\0"\n\t"|, @keywords;
++print $kwdef join qq|"\n\t"|, @keywords;
+ print $kwdef qq|";\n\n|;
+
+ # Emit an array of numerical offsets which will be used to index into the
+@@ -145,7 +147,7 @@ foreach my $name (@keywords)
+
+ # Calculate the cumulative offset of the next keyword,
+ # taking into account the null terminator.
+- $offset += $this_length + 1;
++ $offset += $this_length -1;
+
+ # Update max keyword length.
+ $max_len = $this_length if $max_len < $this_length;
+
+*/
+
+
+static const char aligned_words[] =
+ "abort\0__"
+ "absent\0_"
+ "absolute\0_______"
+ "access\0_"
+ "action\0_"
+ "add\0____"
+ "admin\0__"
+ "after\0__"
+ "aggregate\0______"
+ "all\0____"
+ "also\0___"
+ "alter\0__"
+ "always\0_"
+ "analyse\0"
+ "analyze\0"
+ "and\0____"
+ "any\0____"
+ "array\0__"
+ "as\0_____"
+ "asc\0____"
+ "asensitive\0_____"
+ "assertion\0______"
+ "assignment\0_____"
+ "asymmetric\0_____"
+ "at\0_____"
+ "atomic\0_"
+ "attach\0_"
+ "attribute\0______"
+ "authorization\0__"
+ "backward\0_______"
+ "before\0_"
+ "begin\0__"
+ "between\0"
+ "bigint\0_"
+ "binary\0_"
+ "bit\0____"
+ "boolean\0"
+ "both\0___"
+ "breadth\0"
+ "by\0_____"
+ "cache\0__"
+ "call\0___"
+ "called\0_"
+ "cascade\0"
+ "cascaded\0_______"
+ "case\0___"
+ "cast\0___"
+ "catalog\0"
+ "chain\0__"
+ "char\0___"
+ "character\0______"
+ "characteristics\0"
+ "check\0__"
+ "checkpoint\0_____"
+ "class\0__"
+ "close\0__"
+ "cluster\0"
+ "coalesce\0_______"
+ "collate\0"
+ "collation\0______"
+ "column\0_"
+ "columns\0"
+ "comment\0"
+ "comments\0_______"
+ "commit\0_"
+ "committed\0______"
+ "compression\0____"
+ "concurrently\0___"
+ "configuration\0__"
+ "conflict\0_______"
+ "connection\0_____"
+ "constraint\0_____"
+ "constraints\0____"
+ "content\0"
+ "continue\0_______"
+ "conversion\0_____"
+ "copy\0___"
+ "cost\0___"
+ "create\0_"
+ "cross\0__"
+ "csv\0____"
+ "cube\0___"
+ "current\0"
+ "current_catalog\0"
+ "current_date\0___"
+ "current_role\0___"
+ "current_schema\0_"
+ "current_time\0___"
+ "current_timestamp\0______"
+ "current_user\0___"
+ "cursor\0_"
+ "cycle\0__"
+ "data\0___"
+ "database\0_______"
+ "day\0____"
+ "deallocate\0_____"
+ "dec\0____"
+ "decimal\0"
+ "declare\0"
+ "default\0"
+ "defaults\0_______"
+ "deferrable\0_____"
+ "deferred\0_______"
+ "definer\0"
+ "delete\0_"
+ "delimiter\0______"
+ "delimiters\0_____"
+ "depends\0"
+ "depth\0__"
+ "desc\0___"
+ "detach\0_"
+ "dictionary\0_____"
+ "disable\0"
+ "discard\0"
+ "distinct\0_______"
+ "do\0_____"
+ "document\0_______"
+ "domain\0_"
+ "double\0_"
+ "drop\0___"
+ "each\0___"
+ "else\0___"
+ "enable\0_"
+ "encoding\0_______"
+ "encrypted\0______"
+ "end\0____"
+ "enum\0___"
+ "escape\0_"
+ "event\0__"
+ "except\0_"
+ "exclude\0"
+ "excluding\0______"
+ "exclusive\0______"
+ "execute\0"
+ "exists\0_"
+ "explain\0"
+ "expression\0_____"
+ "extension\0______"
+ "external\0_______"
+ "extract\0"
+ "false\0__"
+ "family\0_"
+ "fetch\0__"
+ "filter\0_"
+ "finalize\0_______"
+ "first\0__"
+ "float\0__"
+ "following\0______"
+ "for\0____"
+ "force\0__"
+ "foreign\0"
+ "format\0_"
+ "forward\0"
+ "freeze\0_"
+ "from\0___"
+ "full\0___"
+ "function\0_______"
+ "functions\0______"
+ "generated\0______"
+ "global\0_"
+ "grant\0__"
+ "granted\0"
+ "greatest\0_______"
+ "group\0__"
+ "grouping\0_______"
+ "groups\0_"
+ "handler\0"
+ "having\0_"
+ "header\0_"
+ "hold\0___"
+ "hour\0___"
+ "identity\0_______"
+ "if\0_____"
+ "ilike\0__"
+ "immediate\0______"
+ "immutable\0______"
+ "implicit\0_______"
+ "import\0_"
+ "in\0_____"
+ "include\0"
+ "including\0______"
+ "increment\0______"
+ "indent\0_"
+ "index\0__"
+ "indexes\0"
+ "inherit\0"
+ "inherits\0_______"
+ "initially\0______"
+ "inline\0_"
+ "inner\0__"
+ "inout\0__"
+ "input\0__"
+ "insensitive\0____"
+ "insert\0_"
+ "instead\0"
+ "int\0____"
+ "integer\0"
+ "intersect\0______"
+ "interval\0_______"
+ "into\0___"
+ "invoker\0"
+ "is\0_____"
+ "isnull\0_"
+ "isolation\0______"
+ "join\0___"
+ "json\0___"
+ "json_array\0_____"
+ "json_arrayagg\0__"
+ "json_object\0____"
+ "json_objectagg\0_"
+ "json_scalar\0____"
+ "json_serialize\0_"
+ "key\0____"
+ "keys\0___"
+ "label\0__"
+ "language\0_______"
+ "large\0__"
+ "last\0___"
+ "lateral\0"
+ "leading\0"
+ "leakproof\0______"
+ "least\0__"
+ "left\0___"
+ "level\0__"
+ "like\0___"
+ "limit\0__"
+ "listen\0_"
+ "load\0___"
+ "local\0__"
+ "localtime\0______"
+ "localtimestamp\0_"
+ "location\0_______"
+ "lock\0___"
+ "locked\0_"
+ "logged\0_"
+ "mapping\0"
+ "match\0__"
+ "matched\0"
+ "materialized\0___"
+ "maxvalue\0_______"
+ "merge\0__"
+ "method\0_"
+ "minute\0_"
+ "minvalue\0_______"
+ "mode\0___"
+ "month\0__"
+ "move\0___"
+ "name\0___"
+ "names\0__"
+ "national\0_______"
+ "natural\0"
+ "nchar\0__"
+ "new\0____"
+ "next\0___"
+ "nfc\0____"
+ "nfd\0____"
+ "nfkc\0___"
+ "nfkd\0___"
+ "no\0_____"
+ "none\0___"
+ "normalize\0______"
+ "normalized\0_____"
+ "not\0____"
+ "nothing\0"
+ "notify\0_"
+ "notnull\0"
+ "nowait\0_"
+ "null\0___"
+ "nullif\0_"
+ "nulls\0__"
+ "numeric\0"
+ "object\0_"
+ "of\0_____"
+ "off\0____"
+ "offset\0_"
+ "oids\0___"
+ "old\0____"
+ "on\0_____"
+ "only\0___"
+ "operator\0_______"
+ "option\0_"
+ "options\0"
+ "or\0_____"
+ "order\0__"
+ "ordinality\0_____"
+ "others\0_"
+ "out\0____"
+ "outer\0__"
+ "over\0___"
+ "overlaps\0_______"
+ "overlay\0"
+ "overriding\0_____"
+ "owned\0__"
+ "owner\0__"
+ "parallel\0_______"
+ "parameter\0______"
+ "parser\0_"
+ "partial\0"
+ "partition\0______"
+ "passing\0"
+ "password\0_______"
+ "placing\0"
+ "plans\0__"
+ "policy\0_"
+ "position\0_______"
+ "preceding\0______"
+ "precision\0______"
+ "prepare\0"
+ "prepared\0_______"
+ "preserve\0_______"
+ "primary\0"
+ "prior\0__"
+ "privileges\0_____"
+ "procedural\0_____"
+ "procedure\0______"
+ "procedures\0_____"
+ "program\0"
+ "publication\0____"
+ "quote\0__"
+ "range\0__"
+ "read\0___"
+ "real\0___"
+ "reassign\0_______"
+ "recheck\0"
+ "recursive\0______"
+ "ref\0____"
+ "references\0_____"
+ "referencing\0____"
+ "refresh\0"
+ "reindex\0"
+ "relative\0_______"
+ "release\0"
+ "rename\0_"
+ "repeatable\0_____"
+ "replace\0"
+ "replica\0"
+ "reset\0__"
+ "restart\0"
+ "restrict\0_______"
+ "return\0_"
+ "returning\0______"
+ "returns\0"
+ "revoke\0_"
+ "right\0__"
+ "role\0___"
+ "rollback\0_______"
+ "rollup\0_"
+ "routine\0"
+ "routines\0_______"
+ "row\0____"
+ "rows\0___"
+ "rule\0___"
+ "savepoint\0______"
+ "scalar\0_"
+ "schema\0_"
+ "schemas\0"
+ "scroll\0_"
+ "search\0_"
+ "second\0_"
+ "security\0_______"
+ "select\0_"
+ "sequence\0_______"
+ "sequences\0______"
+ "serializable\0___"
+ "server\0_"
+ "session\0"
+ "session_user\0___"
+ "set\0____"
+ "setof\0__"
+ "sets\0___"
+ "share\0__"
+ "show\0___"
+ "similar\0"
+ "simple\0_"
+ "skip\0___"
+ "smallint\0_______"
+ "snapshot\0_______"
+ "some\0___"
+ "sql\0____"
+ "stable\0_"
+ "standalone\0_____"
+ "start\0__"
+ "statement\0______"
+ "statistics\0_____"
+ "stdin\0__"
+ "stdout\0_"
+ "storage\0"
+ "stored\0_"
+ "strict\0_"
+ "strip\0__"
+ "subscription\0___"
+ "substring\0______"
+ "support\0"
+ "symmetric\0______"
+ "sysid\0__"
+ "system\0_"
+ "system_user\0____"
+ "table\0__"
+ "tables\0_"
+ "tablesample\0____"
+ "tablespace\0_____"
+ "temp\0___"
+ "template\0_______"
+ "temporary\0______"
+ "text\0___"
+ "then\0___"
+ "ties\0___"
+ "time\0___"
+ "timestamp\0______"
+ "to\0_____"
+ "trailing\0_______"
+ "transaction\0____"
+ "transform\0______"
+ "treat\0__"
+ "trigger\0"
+ "trim\0___"
+ "true\0___"
+ "truncate\0_______"
+ "trusted\0"
+ "type\0___"
+ "types\0__"
+ "uescape\0"
+ "unbounded\0______"
+ "uncommitted\0____"
+ "unencrypted\0____"
+ "union\0__"
+ "unique\0_"
+ "unknown\0"
+ "unlisten\0_______"
+ "unlogged\0_______"
+ "until\0__"
+ "update\0_"
+ "user\0___"
+ "using\0__"
+ "vacuum\0_"
+ "valid\0__"
+ "validate\0_______"
+ "validator\0______"
+ "value\0__"
+ "values\0_"
+ "varchar\0"
+ "variadic\0_______"
+ "varying\0"
+ "verbose\0"
+ "version\0"
+ "view\0___"
+ "views\0__"
+ "volatile\0_______"
+ "when\0___"
+ "where\0__"
+ "whitespace\0_____"
+ "window\0_"
+ "with\0___"
+ "within\0_"
+ "without\0"
+ "work\0___"
+ "wrapper\0"
+ "write\0__"
+ "xml\0____"
+ "xmlattributes\0__"
+ "xmlconcat\0______"
+ "xmlelement\0_____"
+ "xmlexists\0______"
+ "xmlforest\0______"
+ "xmlnamespaces\0__"
+ "xmlparse\0_______"
+ "xmlpi\0__"
+ "xmlroot\0"
+ "xmlserialize\0___"
+ "xmltable\0_______"
+ "year\0___"
+ "yes\0____"
+ "zone\0___";
+
+static const uint16 word_offsets[] = {
+ 0,
+ 8,
+ 16,
+ 32,
+ 40,
+ 48,
+ 56,
+ 64,
+ 72,
+ 88,
+ 96,
+ 104,
+ 112,
+ 120,
+ 128,
+ 136,
+ 144,
+ 152,
+ 160,
+ 168,
+ 176,
+ 192,
+ 208,
+ 224,
+ 240,
+ 248,
+ 256,
+ 264,
+ 280,
+ 296,
+ 312,
+ 320,
+ 328,
+ 336,
+ 344,
+ 352,
+ 360,
+ 368,
+ 376,
+ 384,
+ 392,
+ 400,
+ 408,
+ 416,
+ 424,
+ 440,
+ 448,
+ 456,
+ 464,
+ 472,
+ 480,
+ 496,
+ 512,
+ 520,
+ 536,
+ 544,
+ 552,
+ 560,
+ 576,
+ 584,
+ 600,
+ 608,
+ 616,
+ 624,
+ 640,
+ 648,
+ 664,
+ 680,
+ 696,
+ 712,
+ 728,
+ 744,
+ 760,
+ 776,
+ 784,
+ 800,
+ 816,
+ 824,
+ 832,
+ 840,
+ 848,
+ 856,
+ 864,
+ 872,
+ 888,
+ 904,
+ 920,
+ 936,
+ 952,
+ 976,
+ 992,
+ 1000,
+ 1008,
+ 1016,
+ 1032,
+ 1040,
+ 1056,
+ 1064,
+ 1072,
+ 1080,
+ 1088,
+ 1104,
+ 1120,
+ 1136,
+ 1144,
+ 1152,
+ 1168,
+ 1184,
+ 1192,
+ 1200,
+ 1208,
+ 1216,
+ 1232,
+ 1240,
+ 1248,
+ 1264,
+ 1272,
+ 1288,
+ 1296,
+ 1304,
+ 1312,
+ 1320,
+ 1328,
+ 1336,
+ 1352,
+ 1368,
+ 1376,
+ 1384,
+ 1392,
+ 1400,
+ 1408,
+ 1416,
+ 1432,
+ 1448,
+ 1456,
+ 1464,
+ 1472,
+ 1488,
+ 1504,
+ 1520,
+ 1528,
+ 1536,
+ 1544,
+ 1552,
+ 1560,
+ 1576,
+ 1584,
+ 1592,
+ 1608,
+ 1616,
+ 1624,
+ 1632,
+ 1640,
+ 1648,
+ 1656,
+ 1664,
+ 1672,
+ 1688,
+ 1704,
+ 1720,
+ 1728,
+ 1736,
+ 1744,
+ 1760,
+ 1768,
+ 1784,
+ 1792,
+ 1800,
+ 1808,
+ 1816,
+ 1824,
+ 1832,
+ 1848,
+ 1856,
+ 1864,
+ 1880,
+ 1896,
+ 1912,
+ 1920,
+ 1928,
+ 1936,
+ 1952,
+ 1968,
+ 1976,
+ 1984,
+ 1992,
+ 2000,
+ 2016,
+ 2032,
+ 2040,
+ 2048,
+ 2056,
+ 2064,
+ 2080,
+ 2088,
+ 2096,
+ 2104,
+ 2112,
+ 2128,
+ 2144,
+ 2152,
+ 2160,
+ 2168,
+ 2176,
+ 2192,
+ 2200,
+ 2208,
+ 2224,
+ 2240,
+ 2256,
+ 2272,
+ 2288,
+ 2304,
+ 2312,
+ 2320,
+ 2328,
+ 2344,
+ 2352,
+ 2360,
+ 2368,
+ 2376,
+ 2392,
+ 2400,
+ 2408,
+ 2416,
+ 2424,
+ 2432,
+ 2440,
+ 2448,
+ 2456,
+ 2472,
+ 2488,
+ 2504,
+ 2512,
+ 2520,
+ 2528,
+ 2536,
+ 2544,
+ 2552,
+ 2568,
+ 2584,
+ 2592,
+ 2600,
+ 2608,
+ 2624,
+ 2632,
+ 2640,
+ 2648,
+ 2656,
+ 2664,
+ 2680,
+ 2688,
+ 2696,
+ 2704,
+ 2712,
+ 2720,
+ 2728,
+ 2736,
+ 2744,
+ 2752,
+ 2760,
+ 2776,
+ 2792,
+ 2800,
+ 2808,
+ 2816,
+ 2824,
+ 2832,
+ 2840,
+ 2848,
+ 2856,
+ 2864,
+ 2872,
+ 2880,
+ 2888,
+ 2896,
+ 2904,
+ 2912,
+ 2920,
+ 2928,
+ 2944,
+ 2952,
+ 2960,
+ 2968,
+ 2976,
+ 2992,
+ 3000,
+ 3008,
+ 3016,
+ 3024,
+ 3040,
+ 3048,
+ 3064,
+ 3072,
+ 3080,
+ 3096,
+ 3112,
+ 3120,
+ 3128,
+ 3144,
+ 3152,
+ 3168,
+ 3176,
+ 3184,
+ 3192,
+ 3208,
+ 3224,
+ 3240,
+ 3248,
+ 3264,
+ 3280,
+ 3288,
+ 3296,
+ 3312,
+ 3328,
+ 3344,
+ 3360,
+ 3368,
+ 3384,
+ 3392,
+ 3400,
+ 3408,
+ 3416,
+ 3432,
+ 3440,
+ 3456,
+ 3464,
+ 3480,
+ 3496,
+ 3504,
+ 3512,
+ 3528,
+ 3536,
+ 3544,
+ 3560,
+ 3568,
+ 3576,
+ 3584,
+ 3592,
+ 3608,
+ 3616,
+ 3632,
+ 3640,
+ 3648,
+ 3656,
+ 3664,
+ 3680,
+ 3688,
+ 3696,
+ 3712,
+ 3720,
+ 3728,
+ 3736,
+ 3752,
+ 3760,
+ 3768,
+ 3776,
+ 3784,
+ 3792,
+ 3800,
+ 3816,
+ 3824,
+ 3840,
+ 3856,
+ 3872,
+ 3880,
+ 3888,
+ 3904,
+ 3912,
+ 3920,
+ 3928,
+ 3936,
+ 3944,
+ 3952,
+ 3960,
+ 3968,
+ 3984,
+ 4000,
+ 4008,
+ 4016,
+ 4024,
+ 4040,
+ 4048,
+ 4064,
+ 4080,
+ 4088,
+ 4096,
+ 4104,
+ 4112,
+ 4120,
+ 4128,
+ 4144,
+ 4160,
+ 4168,
+ 4184,
+ 4192,
+ 4200,
+ 4216,
+ 4224,
+ 4232,
+ 4248,
+ 4264,
+ 4272,
+ 4288,
+ 4304,
+ 4312,
+ 4320,
+ 4328,
+ 4336,
+ 4352,
+ 4360,
+ 4376,
+ 4392,
+ 4408,
+ 4416,
+ 4424,
+ 4432,
+ 4440,
+ 4456,
+ 4464,
+ 4472,
+ 4480,
+ 4488,
+ 4504,
+ 4520,
+ 4536,
+ 4544,
+ 4552,
+ 4560,
+ 4576,
+ 4592,
+ 4600,
+ 4608,
+ 4616,
+ 4624,
+ 4632,
+ 4640,
+ 4656,
+ 4672,
+ 4680,
+ 4688,
+ 4696,
+ 4712,
+ 4720,
+ 4728,
+ 4736,
+ 4744,
+ 4752,
+ 4768,
+ 4776,
+ 4784,
+ 4800,
+ 4808,
+ 4816,
+ 4824,
+ 4832,
+ 4840,
+ 4848,
+ 4856,
+ 4864,
+ 4880,
+ 4896,
+ 4912,
+ 4928,
+ 4944,
+ 4960,
+ 4976,
+ 4984,
+ 4992,
+ 5008,
+ 5024,
+ 5032,
+ 5040,
+};
+
+
+#define SCANKEYWORDS_NUM_KEYWORDS 473
+
diff --git a/contrib/bench_hash/bench_hash--1.0.sql b/contrib/bench_hash/bench_hash--1.0.sql
new file mode 100644
index 0000000000..b3a5747432
--- /dev/null
+++ b/contrib/bench_hash/bench_hash--1.0.sql
@@ -0,0 +1,21 @@
+/* src/test/modules/bench_hash/bench_hash--1.0.sql */
+
+-- complain if script is sourced in psql, rather than via CREATE EXTENSION
+\echo Use "CREATE EXTENSION bench_hash" to load this file. \quit
+
+CREATE FUNCTION bench_string_hash(int4)
+RETURNS int
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT;
+
+
+CREATE FUNCTION bench_cstring_hash_unaligned(int4)
+RETURNS int
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT;
+
+CREATE FUNCTION bench_cstring_hash_aligned(int4)
+RETURNS int
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT;
+
diff --git a/contrib/bench_hash/bench_hash.c b/contrib/bench_hash/bench_hash.c
new file mode 100644
index 0000000000..9c9dba93f0
--- /dev/null
+++ b/contrib/bench_hash/bench_hash.c
@@ -0,0 +1,103 @@
+/*-------------------------------------------------------------------------
+ *
+ * bench_hash.c
+ *
+ * Copyright (c) 2023, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/test/modules/bench_hash/bench_hash.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "fmgr.h"
+
+PG_MODULE_MAGIC;
+
+#include "aligned_keywords.h"
+
+#include "common/hashfn.h"
+#include "common/hashfn_unstable.h"
+#include "miscadmin.h"
+#include "utils/memutils.h"
+
+
+PG_FUNCTION_INFO_V1(bench_string_hash);
+Datum
+bench_string_hash(PG_FUNCTION_ARGS)
+{
+ int32 count = PG_GETARG_INT32(0);
+ uint32 hash = 0;
+
+ while (count-- > 0)
+ {
+ for (int i=0; i< SCANKEYWORDS_NUM_KEYWORDS; i++)
+ {
+ int idx = word_offsets[i];
+ int s_len = strlen(&aligned_words[idx]);
+ hash += hash_bytes((const unsigned char *) &aligned_words[idx], s_len);
+ }
+ CHECK_FOR_INTERRUPTS();
+ }
+
+ PG_RETURN_INT32(hash);
+}
+
+
+PG_FUNCTION_INFO_V1(bench_cstring_hash_unaligned);
+Datum
+bench_cstring_hash_unaligned(PG_FUNCTION_ARGS)
+{
+ int32 count = PG_GETARG_INT32(0);
+ uint32 hash = 0;
+
+ char* p = (char*) palloc(5048);
+ memcpy(p, aligned_words, 5048);
+
+ while (count-- > 0)
+ {
+ for (int i=0; i< SCANKEYWORDS_NUM_KEYWORDS; i++)
+ {
+ int idx = word_offsets[i];
+ int s_len;
+ fasthash_state hs;
+
+ fasthash_init(&hs, FH_UNKNOWN_LENGTH, 0);
+ s_len = fasthash_accum_cstring_unaligned(&hs, &p[idx]);
+ hash += fasthash_final32(&hs, s_len);
+ }
+ CHECK_FOR_INTERRUPTS();
+ }
+
+ PG_RETURN_INT32(hash);
+}
+
+
+PG_FUNCTION_INFO_V1(bench_cstring_hash_aligned);
+Datum
+bench_cstring_hash_aligned(PG_FUNCTION_ARGS)
+{
+ int32 count = PG_GETARG_INT32(0);
+ uint32 hash = 0;
+
+ char* p = (char*) palloc(5048);
+ memcpy(p, aligned_words, 5048);
+
+ while (count-- > 0)
+ {
+ for (int i=0; i< SCANKEYWORDS_NUM_KEYWORDS; i++)
+ {
+ int idx = word_offsets[i];
+ int s_len;
+ fasthash_state hs;
+
+ fasthash_init(&hs, FH_UNKNOWN_LENGTH, 0);
+ s_len = fasthash_accum_cstring_aligned(&hs, &p[idx]);
+ hash += fasthash_final32(&hs, s_len);
+ }
+ CHECK_FOR_INTERRUPTS();
+ }
+
+ PG_RETURN_INT32(hash);
+}
diff --git a/contrib/bench_hash/bench_hash.control b/contrib/bench_hash/bench_hash.control
new file mode 100644
index 0000000000..ffc63858d2
--- /dev/null
+++ b/contrib/bench_hash/bench_hash.control
@@ -0,0 +1,5 @@
+# bench_hash extension
+comment = 'benchmark some hash functions'
+default_version = '1.0'
+module_pathname = '$libdir/bench_hash'
+relocatable = true
diff --git a/contrib/bench_hash/meson.build b/contrib/bench_hash/meson.build
new file mode 100644
index 0000000000..f8d88d8b5c
--- /dev/null
+++ b/contrib/bench_hash/meson.build
@@ -0,0 +1,19 @@
+# Copyright (c) 2022-2023, PostgreSQL Global Development Group
+
+bench_hash_sources = files(
+ 'bench_hash.c',
+)
+
+bench_hash = shared_module('bench_hash',
+ bench_hash_sources,
+# link_with: pgport_srv,
+ kwargs: contrib_mod_args,
+)
+contrib_targets += bench_hash
+
+install_data(
+ 'bench_hash.control',
+ 'bench_hash--1.0.sql',
+ kwargs: contrib_data_args,
+)
+
diff --git a/contrib/meson.build b/contrib/meson.build
index c0b267c632..0e99195476 100644
--- a/contrib/meson.build
+++ b/contrib/meson.build
@@ -12,6 +12,7 @@ contrib_doc_args = {
'install_dir': contrib_doc_dir,
}
+subdir('bench_hash')
subdir('adminpack')
subdir('amcheck')
subdir('auth_delay')
--
2.43.0