From b5498a26deba8d3112dbf4da5375ccd9db4ff375 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 21 Apr 2006 16:45:12 +0000 Subject: [PATCH] Add some optional code (conditionally compiled under #ifdef LWLOCK_STATS) to track the number of LWLock acquisitions and the number of times we block waiting for an LWLock, on a per-process basis. After having needed this twice in the past few months, seems like it should go into CVS. --- src/backend/storage/lmgr/lwlock.c | 59 ++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index a2a6592d5a..f63318cf0e 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/lmgr/lwlock.c,v 1.38 2006/03/05 15:58:39 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/storage/lmgr/lwlock.c,v 1.39 2006/04/21 16:45:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -25,6 +25,7 @@ #include "access/multixact.h" #include "access/subtrans.h" #include "miscadmin.h" +#include "storage/ipc.h" #include "storage/lwlock.h" #include "storage/proc.h" #include "storage/spin.h" @@ -84,6 +85,13 @@ NON_EXEC_STATIC LWLockPadded *LWLockArray = NULL; static int num_held_lwlocks = 0; static LWLockId held_lwlocks[MAX_SIMUL_LWLOCKS]; +#ifdef LWLOCK_STATS +static int counts_for_pid = 0; +static int *sh_acquire_counts; +static int *ex_acquire_counts; +static int *block_counts; +#endif + #ifdef LOCK_DEBUG bool Trace_lwlocks = false; @@ -109,6 +117,31 @@ LOG_LWDEBUG(const char *where, LWLockId lockid, const char *msg) #define LOG_LWDEBUG(a,b,c) #endif /* LOCK_DEBUG */ +#ifdef LWLOCK_STATS + +static void +print_lwlock_stats(int code, Datum arg) +{ + int i; + int *LWLockCounter = (int *) ((char *) LWLockArray - 2 * sizeof(int)); + int numLocks = LWLockCounter[1]; + + /* Grab an LWLock to keep different backends from mixing reports */ + LWLockAcquire(0, LW_EXCLUSIVE); + + for (i = 0; i < numLocks; i++) + { + if (sh_acquire_counts[i] || ex_acquire_counts[i] || block_counts[i]) + fprintf(stderr, "PID %d lwlock %d: shacq %u exacq %u blk %u\n", + MyProcPid, i, sh_acquire_counts[i], ex_acquire_counts[i], + block_counts[i]); + } + + LWLockRelease(0); +} + +#endif /* LWLOCK_STATS */ + /* * Compute number of LWLocks to allocate. @@ -263,6 +296,26 @@ LWLockAcquire(LWLockId lockid, LWLockMode mode) PRINT_LWDEBUG("LWLockAcquire", lockid, lock); +#ifdef LWLOCK_STATS + /* Set up local count state first time through in a given process */ + if (counts_for_pid != MyProcPid) + { + int *LWLockCounter = (int *) ((char *) LWLockArray - 2 * sizeof(int)); + int numLocks = LWLockCounter[1]; + + sh_acquire_counts = calloc(numLocks, sizeof(int)); + ex_acquire_counts = calloc(numLocks, sizeof(int)); + block_counts = calloc(numLocks, sizeof(int)); + counts_for_pid = MyProcPid; + on_shmem_exit(print_lwlock_stats, 0); + } + /* Count lock acquisition attempts */ + if (mode == LW_EXCLUSIVE) + ex_acquire_counts[lockid]++; + else + sh_acquire_counts[lockid]++; +#endif /* LWLOCK_STATS */ + /* * We can't wait if we haven't got a PGPROC. This should only occur * during bootstrap or shared memory initialization. Put an Assert here @@ -369,6 +422,10 @@ LWLockAcquire(LWLockId lockid, LWLockMode mode) */ LOG_LWDEBUG("LWLockAcquire", lockid, "waiting"); +#ifdef LWLOCK_STATS + block_counts[lockid]++; +#endif + for (;;) { /* "false" means cannot accept cancel/die interrupt here. */