]> granicus.if.org Git - postgresql/commitdiff
Add some optional code (conditionally compiled under #ifdef LWLOCK_STATS)
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 21 Apr 2006 16:45:12 +0000 (16:45 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 21 Apr 2006 16:45:12 +0000 (16:45 +0000)
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

index a2a6592d5a0479073af4c6ca65bb5bbbff0da0cd..f63318cf0e47fd687ee3cdf1b3766c8d2a9bf320 100644 (file)
@@ -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. */