Hope this patch will be usefull/

On Mon, Sep 18, 2023 at 5:47 PM Sergey Sergey <ioxg...@gmail.com> wrote:

> While replaying our production workload we have found Postgres spending a
> lot of time inside TimescaleDB planner. The planner itself need an
> information about whether a table involved is a TimescaleDB hypertable. So
> planner need an access to TimescaleDB internal metainformation tables. This
> planner access become extremely slow when you have a lot of tables involved
> and you are beyond fast-path lock limit
>
> This humble example makes only 2330 tps on REL_15_STABLE but 27041tps on
> patched version with 64 slots for fast-path locks.
>
> \set bid random(1,1000)
>
> BEGIN;
> select bbalance from pgbench_branches where bid = :bid
> UNION
> select bbalance from pgbench_branches2 where bid = :bid
> UNION
> select bbalance from pgbench_branches3 where bid = :bid
> UNION
> select bbalance from pgbench_branches4 where bid = :bid
> UNION
> select bbalance from pgbench_branches5 where bid = :bid
> UNION
> select bbalance from pgbench_branches6 where bid = :bid
> UNION
> select bbalance from pgbench_branches7 where bid = :bid
> UNION
> select bbalance from pgbench_branches8 where bid = :bid
> UNION
> select bbalance from pgbench_branches9 where bid = :bid
> UNION
> select bbalance from pgbench_branches10 where bid = :bid
> UNION
> select bbalance from pgbench_branches11 where bid = :bid
> UNION
> select bbalance from pgbench_branches12 where bid = :bid
> UNION
> select bbalance from pgbench_branches13 where bid = :bid
> UNION
> select bbalance from pgbench_branches14 where bid = :bid
> UNION
> select bbalance from pgbench_branches15 where bid = :bid
> UNION
> select bbalance from pgbench_branches16 where bid = :bid
> UNION
> select bbalance from pgbench_branches17 where bid = :bid
> UNION
> select bbalance from pgbench_branches18 where bid = :bid
> UNION
> select bbalance from pgbench_branches19 where bid = :bid
> UNION
> select bbalance from pgbench_branches20 where bid = :bid;
> END;
>
> First i try to make the number of fast-path locks as a GUC parameter. But
> it implies a lot of changes with PGPROC structure. Next I implement it as a
> compile-time parameter.
>
diff --git a/home/nikor/tmp/postgres/configure.ac b/configure.ac
index c216ac4447..558e17273c 100644
--- a/home/nikor/tmp/postgres/configure.ac
+++ b/configure.ac
@@ -283,6 +283,23 @@ AC_DEFINE_UNQUOTED([BLCKSZ], ${BLCKSZ}, [
  Changing BLCKSZ requires an initdb.
 ])
 
+#
+# Fastlock size
+#
+AC_MSG_CHECKING([for fastlock size])
+PGAC_ARG_REQ(with, fastlocksize, [FASTLOCKSIZE], [set fastlock array size [16]],
+             [fastlocksize=$withval],
+             [fastlocksize=16])
+AC_MSG_RESULT([${fastlocksize}])
+
+AC_DEFINE_UNQUOTED([FP_LOCK_SLOTS_PER_BACKEND], ${fastlocksize}, [
+ Size of a fastlock slots. Large values can help when transaction
+ touch a lot of objects.
+
+ Changes requires restart.
+
+])
+
 #
 # Relation segment size
 #
diff --git a/home/nikor/tmp/postgres/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 86fc5576af..81e0d5f839 100644
--- a/home/nikor/tmp/postgres/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -191,18 +191,18 @@ static bool IsRelationExtensionLockHeld PG_USED_FOR_ASSERTS_ONLY = false;
 #define FAST_PATH_LOCKNUMBER_OFFSET		1
 #define FAST_PATH_MASK					((1 << FAST_PATH_BITS_PER_SLOT) - 1)
 #define FAST_PATH_GET_BITS(proc, n) \
-	(((proc)->fpLockBits >> (FAST_PATH_BITS_PER_SLOT * n)) & FAST_PATH_MASK)
+	((proc)->fpLockBits[n] & FAST_PATH_MASK)
 #define FAST_PATH_BIT_POSITION(n, l) \
 	(AssertMacro((l) >= FAST_PATH_LOCKNUMBER_OFFSET), \
 	 AssertMacro((l) < FAST_PATH_BITS_PER_SLOT+FAST_PATH_LOCKNUMBER_OFFSET), \
 	 AssertMacro((n) < FP_LOCK_SLOTS_PER_BACKEND), \
-	 ((l) - FAST_PATH_LOCKNUMBER_OFFSET + FAST_PATH_BITS_PER_SLOT * (n)))
+	 ((l) - FAST_PATH_LOCKNUMBER_OFFSET ))
 #define FAST_PATH_SET_LOCKMODE(proc, n, l) \
-	 (proc)->fpLockBits |= UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l)
+	 (proc)->fpLockBits[n] |= UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l)
 #define FAST_PATH_CLEAR_LOCKMODE(proc, n, l) \
-	 (proc)->fpLockBits &= ~(UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l))
+	 (proc)->fpLockBits[n] &= ~(UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l))
 #define FAST_PATH_CHECK_LOCKMODE(proc, n, l) \
-	 ((proc)->fpLockBits & (UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l)))
+	 ((proc)->fpLockBits[n] & (UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l)))
 
 /*
  * The fast-path lock mechanism is concerned only with relation locks on
diff --git a/home/nikor/tmp/postgres/src/include/pg_config.h.in b/src/include/pg_config.h.in
index d09e9f9a1c..c8fc4f9e3f 100644
--- a/home/nikor/tmp/postgres/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -62,6 +62,14 @@
 # define gettimeofday(a,b) gettimeofday(a)
 #endif
 
+/* Size of a fastlock array. 
+   We allow a small number of "weak" relation locks (AccessShareLock,
+   RowShareLock, RowExclusiveLock) to be recorded in the PGPROC structure
+   rather than the main lock table.  This eases contention on the lock
+   manager LWLocks.  See storage/lmgr/README for additional details.
+*/
+#undef FP_LOCK_SLOTS_PER_BACKEND
+
 /* Define to 1 if you have the `append_history' function. */
 #undef HAVE_APPEND_HISTORY
 
diff --git a/home/nikor/tmp/postgres/src/include/storage/proc.h b/src/include/storage/proc.h
index 2579e619eb..5303675a3a 100644
--- a/home/nikor/tmp/postgres/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -74,14 +74,6 @@ struct XidCache
  */
 #define		PROC_XMIN_FLAGS (PROC_IN_VACUUM | PROC_IN_SAFE_IC)
 
-/*
- * We allow a small number of "weak" relation locks (AccessShareLock,
- * RowShareLock, RowExclusiveLock) to be recorded in the PGPROC structure
- * rather than the main lock table.  This eases contention on the lock
- * manager LWLocks.  See storage/lmgr/README for additional details.
- */
-#define		FP_LOCK_SLOTS_PER_BACKEND 16
-
 /*
  * An invalid pgprocno.  Must be larger than the maximum number of PGPROC
  * structures we could possibly have.  See comments for MAX_BACKENDS.
@@ -282,7 +274,7 @@ struct PGPROC
 
 	/* Lock manager data, recording fast-path locks taken by this backend. */
 	LWLock		fpInfoLock;		/* protects per-backend fast-path state */
-	uint64		fpLockBits;		/* lock modes held for each fast-path slot */
+	uint8		fpLockBits[FP_LOCK_SLOTS_PER_BACKEND];		/* lock modes held for each fast-path slot */
 	Oid			fpRelId[FP_LOCK_SLOTS_PER_BACKEND]; /* slots for rel oids */
 	bool		fpVXIDLock;		/* are we holding a fast-path VXID lock? */
 	LocalTransactionId fpLocalTransactionId;	/* lxid for fast-path VXID
diff --git a/home/nikor/tmp/postgres/configure b/./configure
index 57607d79df..58228f42fa 100755
--- a/home/nikor/tmp/postgres/configure
+++ b/./configure
@@ -806,6 +806,7 @@ infodir
 docdir
 oldincludedir
 includedir
+runstatedir
 localstatedir
 sharedstatedir
 sysconfdir
@@ -845,6 +846,7 @@ enable_coverage
 enable_dtrace
 enable_tap_tests
 with_blocksize
+with_fastlocksize
 with_segsize
 with_wal_blocksize
 with_CC
@@ -950,6 +952,7 @@ datadir='${datarootdir}'
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
 docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@@ -1202,6 +1205,15 @@ do
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
 
+  -runstatedir | --runstatedir | --runstatedi | --runstated \
+  | --runstate | --runstat | --runsta | --runst | --runs \
+  | --run | --ru | --r)
+    ac_prev=runstatedir ;;
+  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+  | --run=* | --ru=* | --r=*)
+    runstatedir=$ac_optarg ;;
+
   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
     ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1339,7 +1351,7 @@ fi
 for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
 		datadir sysconfdir sharedstatedir localstatedir includedir \
 		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-		libdir localedir mandir
+		libdir localedir mandir runstatedir
 do
   eval ac_val=\$$ac_var
   # Remove trailing slashes.
@@ -1492,6 +1504,7 @@ Fine tuning of the installation directories:
   --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
   --libdir=DIR            object code libraries [EPREFIX/lib]
   --includedir=DIR        C header files [PREFIX/include]
   --oldincludedir=DIR     C header files for non-gcc [/usr/include]
@@ -1555,6 +1568,8 @@ Optional Packages:
   --with-pgport=PORTNUM   set default port number [5432]
   --with-blocksize=BLOCKSIZE
                           set table block size in kB [8]
+  --with-fastlocksize=FASTLOCKSIZE
+                          set fastlock array size [16]
   --with-segsize=SEGSIZE  set table segment size in GB [1]
   --with-wal-blocksize=BLOCKSIZE
                           set WAL block size in kB [8]
@@ -3735,6 +3750,43 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+#
+# Fastlock size
+#
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fastlock size" >&5
+$as_echo_n "checking for fastlock size... " >&6; }
+
+
+
+# Check whether --with-fastlocksize was given.
+if test "${with_fastlocksize+set}" = set; then :
+  withval=$with_fastlocksize;
+  case $withval in
+    yes)
+      as_fn_error $? "argument required for --with-fastlocksize option" "$LINENO" 5
+      ;;
+    no)
+      as_fn_error $? "argument required for --with-fastlocksize option" "$LINENO" 5
+      ;;
+    *)
+      fastlocksize=$withval
+      ;;
+  esac
+
+else
+  fastlocksize=16
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${fastlocksize}" >&5
+$as_echo "${fastlocksize}" >&6; }
+
+
+cat >>confdefs.h <<_ACEOF
+#define FP_LOCK_SLOTS_PER_BACKEND ${fastlocksize}
+_ACEOF
+
+
 #
 # Relation segment size
 #
@@ -15780,7 +15832,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -15826,7 +15878,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -15850,7 +15902,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -15895,7 +15947,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -15919,7 +15971,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];

Reply via email to