From 74bad4bbcff9ea4a9a68f91618c84854dab24701 Mon Sep 17 00:00:00 2001
From: Stepan Neretin <sncfmgg@gmail.com>
Date: Sat, 8 Jun 2024 01:29:42 +0700
Subject: [PATCH v42 6/6] Implemented benchmarking for optimized sorting

This commit adds benchmarking functions to compare the performance of two list sorting operations: bench_int_sort and bench_oid_sort. These functions measure the execution time of sorting lists of integers and OIDs, respectively, using different algorithms (list_sort and custom sorting functions). Random lists of specified sizes are generated, sorted using both methods, and their execution times are recorded. The percentage difference in execution time between the two methods is also calculated. This commit aims to provide insights into the efficiency of the sorting algorithms used.
---
 contrib/Makefile                              |   1 +
 contrib/bench_sort_improvements/Makefile      |  20 ++++
 contrib/bench_sort_improvements/bench.c       | 105 ++++++++++++++++++
 .../bench_sort_improvements--1.0.sql          |   3 +
 .../bench_sort_improvements.control           |   5 +
 5 files changed, 134 insertions(+)
 create mode 100644 contrib/bench_sort_improvements/Makefile
 create mode 100644 contrib/bench_sort_improvements/bench.c
 create mode 100644 contrib/bench_sort_improvements/bench_sort_improvements--1.0.sql
 create mode 100644 contrib/bench_sort_improvements/bench_sort_improvements.control

diff --git a/contrib/Makefile b/contrib/Makefile
index abd780f277..a1ee9defc2 100644
--- a/contrib/Makefile
+++ b/contrib/Makefile
@@ -10,6 +10,7 @@ SUBDIRS = \
 		auto_explain	\
 		basic_archive	\
 		basebackup_to_shell	\
+		bench_sort_improvements \
 		bloom		\
 		btree_gin	\
 		btree_gist	\
diff --git a/contrib/bench_sort_improvements/Makefile b/contrib/bench_sort_improvements/Makefile
new file mode 100644
index 0000000000..46458ee76c
--- /dev/null
+++ b/contrib/bench_sort_improvements/Makefile
@@ -0,0 +1,20 @@
+MODULE_big = bench_sort_improvements
+
+OBJS = \
+	$(WIN32RES) \
+	bench.o
+
+EXTENSION = bench_sort_improvements
+
+DATA = bench_sort_improvements--1.0.sql
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = contrib/bench_sort_improvements
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/contrib/bench_sort_improvements/bench.c b/contrib/bench_sort_improvements/bench.c
new file mode 100644
index 0000000000..77d5c7fa37
--- /dev/null
+++ b/contrib/bench_sort_improvements/bench.c
@@ -0,0 +1,105 @@
+#include "postgres.h"
+#include "fmgr.h"
+#include "utils/builtins.h"
+#include "nodes/pg_list.h"
+#include <limits.h>
+#include <time.h>
+
+
+PG_MODULE_MAGIC;
+
+Datum bench_int_sort(PG_FUNCTION_ARGS);
+Datum bench_oid_sort(PG_FUNCTION_ARGS);
+
+PG_FUNCTION_INFO_V1(bench_oid_sort);
+PG_FUNCTION_INFO_V1(bench_int_sort);
+
+Datum
+bench_oid_sort(PG_FUNCTION_ARGS)
+{
+    int32 list_size = PG_GETARG_INT32(0);
+    List *list_first = NIL;
+    List *list_second = NIL;
+    Oid random_oid;
+    struct timespec start, end;
+    long time_spent_first;
+    long time_spent_second;
+    double percentage_difference = 0.0;
+    char *result_message;
+
+    for (int i = 0; i < list_size; i++)
+    {
+        random_oid = (Oid) (random() % (UINT_MAX - 1) + 1); 
+        list_first = lappend_oid(list_first, random_oid);
+        list_second = lappend_oid(list_second, random_oid);
+    }
+
+    // Timing the first sort function
+    clock_gettime(CLOCK_MONOTONIC, &start);
+    list_sort(list_first, list_oid_cmp);
+    clock_gettime(CLOCK_MONOTONIC, &end);
+    time_spent_first = (end.tv_sec - start.tv_sec) * 1000000000L + (end.tv_nsec - start.tv_nsec);
+
+    // Timing the second sort function
+    clock_gettime(CLOCK_MONOTONIC, &start);
+    list_oid_sort(list_second);
+    clock_gettime(CLOCK_MONOTONIC, &end);
+    time_spent_second = (end.tv_sec - start.tv_sec) * 1000000000L + (end.tv_nsec - start.tv_nsec);
+
+    percentage_difference = ((double)(time_spent_first - time_spent_second) / time_spent_first) * 100.0;
+
+    list_free(list_first);
+    list_free(list_second);
+    
+    result_message = psprintf("Time taken by list_sort: %ld ns, Time taken by list_oid_sort: %ld ns, Percentage difference: %.2f%%", 
+                              time_spent_first, time_spent_second, percentage_difference);
+    PG_RETURN_TEXT_P(cstring_to_text(result_message));
+}
+
+Datum
+bench_int_sort(PG_FUNCTION_ARGS)
+{
+    int32 list_size = PG_GETARG_INT32(0);
+    List *list_first = NIL;
+    List *list_second = NIL;
+    int random_int;
+    struct timespec start, end;
+    long time_spent_first;
+    long time_spent_second;
+    double percentage_difference = 0.0;
+    char *result_message;
+
+    for (int i = 0; i < list_size; i++)
+    {
+        random_int = rand(); 
+        list_first = lappend_int(list_first, random_int); 
+        list_second = lappend_int(list_second, random_int); 
+    }
+
+    // Timing the first sort function
+    clock_gettime(CLOCK_MONOTONIC, &start);
+    list_sort(list_first, list_oid_cmp);
+    clock_gettime(CLOCK_MONOTONIC, &end);
+    time_spent_first = (end.tv_sec - start.tv_sec) * 1000000000L + (end.tv_nsec - start.tv_nsec);
+
+    // Timing the second sort function
+    clock_gettime(CLOCK_MONOTONIC, &start);
+    list_int_sort(list_second);
+    clock_gettime(CLOCK_MONOTONIC, &end);
+    time_spent_second = (end.tv_sec - start.tv_sec) * 1000000000L + (end.tv_nsec - start.tv_nsec);
+
+    percentage_difference = ((double)(time_spent_first - time_spent_second) / time_spent_first) * 100.0;
+
+    list_free(list_first);
+    list_free(list_second);
+    
+    result_message = psprintf("Time taken by list_sort: %ld ns, Time taken by list_int_sort: %ld ns, Percentage difference: %.2f%%", 
+                              time_spent_first, time_spent_second, percentage_difference);
+    PG_RETURN_TEXT_P(cstring_to_text(result_message));
+}
+
+void
+_PG_init()
+{
+    srand(time(NULL));
+}
\ No newline at end of file
diff --git a/contrib/bench_sort_improvements/bench_sort_improvements--1.0.sql b/contrib/bench_sort_improvements/bench_sort_improvements--1.0.sql
new file mode 100644
index 0000000000..97b75d368d
--- /dev/null
+++ b/contrib/bench_sort_improvements/bench_sort_improvements--1.0.sql
@@ -0,0 +1,3 @@
+create function bench_oid_sort(integer) returns text AS 'MODULE_PATHNAME', 'bench_oid_sort' LANGUAGE C;
+
+create function bench_int_sort(integer) returns text AS 'MODULE_PATHNAME', 'bench_int_sort' LANGUAGE C;
diff --git a/contrib/bench_sort_improvements/bench_sort_improvements.control b/contrib/bench_sort_improvements/bench_sort_improvements.control
new file mode 100644
index 0000000000..7dc05056ac
--- /dev/null
+++ b/contrib/bench_sort_improvements/bench_sort_improvements.control
@@ -0,0 +1,5 @@
+# fuzzystrmatch extension
+comment = 'test extension'
+default_version = '1.0'
+module_pathname = '$libdir/bench_sort_improvements'
+relocatable = true
-- 
2.34.1

