lwlock_instrumentation.patch
application/octet-stream
Filename: lwlock_instrumentation.patch
Type: application/octet-stream
Part: 0
Message:
Patch LWlocks instrumentation
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/storage/lmgr/lwlock.c | 0 | 0 |
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index f2ccbe1..729c6d8 100644
*** a/src/backend/storage/lmgr/lwlock.c
--- b/src/backend/storage/lmgr/lwlock.c
***************
*** 29,34 ****
--- 29,55 ----
#include "storage/ipc.h"
#include "storage/proc.h"
#include "storage/spin.h"
+ #include "portability/instr_time.h"
+
+ /* displays counters (number of lock acquires, etc)
+ * on process exit */
+ #define LWLOCK_STATS
+
+ #ifdef LWLOCK_STATS
+
+ /* also displays cumulative timings of time spent
+ * waiting and holding locks
+ * (depends on LWLOCK_STATS)
+ */
+ #define LWLOCK_TIMING_STATS
+
+ /* displays only locks which were waited on more than
+ * this amount of seconds (set to 0 to display all)
+ * (depends on LWLOCK_TIMING_STATS)
+ */
+ #define LWLOCKS_STATS_TIME_DISPLAY_THRESHOLD 0.1
+ #endif /* LWLOCK_STATS */
+
/* We use the ShmemLock spinlock to protect LWLockAssign */
*************** static LWLockId held_lwlocks[MAX_SIMUL_L
*** 88,100 ****
static int lock_addin_request = 0;
static bool lock_addin_request_allowed = true;
- #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,114 ----
*************** LOG_LWDEBUG(const char *where, LWLockId
*** 121,146 ****
#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 */
--- 135,282 ----
#ifdef LWLOCK_STATS
+ typedef struct
+ {
+ /* Process-local Counters for the number of times the lock has been ... */
+ int count_acquired_share; /* acquired in SHARE mode */
+ int count_waited_share; /* and it needed to wait */
+
+ int count_acquired_exclusive; /* acquired in EXCLUSIVEmode */
+ int count_waited_exclusive; /* and it needed to wait */
+
+ #ifdef LWLOCK_TIMING_STATS
+ /* Process local sum of time during which ... */
+ instr_time time_waited_share; /* we waited to get a SHARE lock */
+ instr_time time_held_share; /* we held the SHARE lock */
+ instr_time time_waited_exclusive; /* we waited to get an EXCLUSIVE lock */
+ instr_time time_held_exclusive; /* we held the EXCLUSIVE lock */
+
+ instr_time ta, th; /* temp variables */
+ #endif
+ } LWLockStatsData;
+
+ static int counts_for_pid = 0;
+ static LWLockStatsData *lwlock_stats;
+ #ifdef LWLOCK_TIMING_STATS
+ static instr_time lwlock_stats_begin_time;
+ #endif
+
+ static const char* lwlock_stats_lock_name( LWLockId id )
+ {
+ static const char * names[] = {
+ "BufFreelist",
+ "ShmemIndex",
+ "OidGen",
+ "XidGen",
+ "ProcArray",
+ "SInvalRead",
+ "SInvalWrite",
+ "WALInsert",
+ "WALWrite",
+ "ControlFile",
+ "Checkpoint",
+ "CLogControl",
+ "SubtransControl",
+ "MultiXactGen",
+ "MultiXactOffsetControl",
+ "MultiXactMemberControl",
+ "RelCacheInit",
+ "BgWriterComm",
+ "TwoPhaseState",
+ "TablespaceCreate",
+ "BtreeVacuum",
+ "AddinShmemInit",
+ "Autovacuum",
+ "AutovacuumSchedule",
+ "SyncScan" };
+
+ if( id >= 0 && id < (sizeof( names )/sizeof( names[0] )))
+ return names[id];
+ else
+ return "";
+ }
+
static void
print_lwlock_stats(int code, Datum arg)
{
! int i, lines=0;
int *LWLockCounter = (int *) ((char *) LWLockArray - 2 * sizeof(int));
int numLocks = LWLockCounter[1];
+ #ifdef LWLOCK_TIMING_STATS
+ instr_time end_time;
+ double total_percents;
+ INSTR_TIME_SET_CURRENT( end_time );
+ INSTR_TIME_SUBTRACT( end_time, lwlock_stats_begin_time );
+ total_percents = 100.0 / INSTR_TIME_GET_DOUBLE( end_time );
+ #endif
+ fprintf( stderr, "\n-------- Lock stats for PID %d\n", MyProcPid );
+
/* Grab an LWLock to keep different backends from mixing reports */
LWLockAcquire(0, LW_EXCLUSIVE);
for (i = 0; i < numLocks; i++)
{
! LWLockStatsData *p = &lwlock_stats[i];
! #ifdef LWLOCK_TIMING_STATS
! double time_waited_share = INSTR_TIME_GET_DOUBLE(p->time_waited_share );
! double time_held_share = INSTR_TIME_GET_DOUBLE(p->time_held_share );
! double time_waited_exclusive = INSTR_TIME_GET_DOUBLE(p->time_waited_exclusive);
! double time_held_exclusive = INSTR_TIME_GET_DOUBLE(p->time_held_exclusive );
! #endif
!
! if( !( p->count_waited_share || p->count_waited_exclusive ))
! continue;
!
! #ifdef LWLOCK_TIMING_STATS
! if( time_waited_share < LWLOCKS_STATS_TIME_DISPLAY_THRESHOLD
! && time_waited_exclusive < LWLOCKS_STATS_TIME_DISPLAY_THRESHOLD )
! continue;
! #endif
!
! #ifdef LWLOCK_TIMING_STATS
! if( !(lines++ & 15) )
! fprintf( stderr, " PID Lock ShAcq ShWait ShWaitT ShHeldT ExAcq "
! "ExWait ExWaitT ExHeldT Name\n" );
!
! fprintf( stderr,
! "%7d %7d %10d %10d %11.02f %11.02f %10d %10d %11.02f (%6.02f %%) %11.02f (%6.02f %%) %s\n",
! MyProcPid, i,
! p->count_acquired_share, p->count_waited_share, time_waited_share, time_held_share,
! p->count_acquired_exclusive, p->count_waited_exclusive,
! time_waited_exclusive, time_waited_exclusive * total_percents,
! time_held_exclusive, time_held_exclusive * total_percents,
! lwlock_stats_lock_name( i ));
! #else
! if( !(lines++ & 15) )
! fprintf( stderr, " PID Lock ShAcq ShWait ExAcq ExWait Name\n" );
!
! fprintf( stderr,
! "%7d %7d %10d %10d %10d %10d %s\n",
! MyProcPid, i,
! p->count_acquired_share, p->count_waited_share,
! p->count_acquired_exclusive, p->count_waited_exclusive,
! lwlock_stats_lock_name( i ));
! #endif
}
LWLockRelease(0);
}
+
+ static void lock_stats_setup( void )
+ {
+ int *LWLockCounter = (int *) ((char *) LWLockArray - 2 * sizeof(int));
+ int numLocks = LWLockCounter[1];
+
+ lwlock_stats = calloc(numLocks, sizeof(LWLockStatsData));
+ counts_for_pid = MyProcPid;
+
+ #ifdef LWLOCK_TIMING_STATS
+ INSTR_TIME_SET_CURRENT( lwlock_stats_begin_time );
+ #endif
+
+ on_shmem_exit(print_lwlock_stats, 0);
+ }
#endif /* LWLOCK_STATS */
*************** LWLockAcquire(LWLockId lockid, LWLockMod
*** 321,341 ****
#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 */
/*
--- 457,471 ----
#ifdef LWLOCK_STATS
/* Set up local count state first time through in a given process */
if (counts_for_pid != MyProcPid)
! lock_stats_setup();
!
/* Count lock acquisition attempts */
! if (mode == LW_EXCLUSIVE) lwlock_stats[lockid].count_acquired_exclusive++;
! else lwlock_stats[lockid].count_acquired_share++;
! #ifdef LWLOCK_TIMING_STATS
! /* record start of wait time and lock mode */
! INSTR_TIME_SET_CURRENT( lwlock_stats[lockid].ta );
! #endif
#endif /* LWLOCK_STATS */
/*
*************** LWLockAcquire(LWLockId lockid, LWLockMod
*** 445,451 ****
LOG_LWDEBUG("LWLockAcquire", lockid, "waiting");
#ifdef LWLOCK_STATS
! block_counts[lockid]++;
#endif
TRACE_POSTGRESQL_LWLOCK_WAIT_START(lockid, mode);
--- 575,583 ----
LOG_LWDEBUG("LWLockAcquire", lockid, "waiting");
#ifdef LWLOCK_STATS
! /* count lock waits */
! if (mode == LW_EXCLUSIVE) lwlock_stats[lockid].count_waited_exclusive++;
! else lwlock_stats[lockid].count_waited_share++;
#endif
TRACE_POSTGRESQL_LWLOCK_WAIT_START(lockid, mode);
*************** LWLockAcquire(LWLockId lockid, LWLockMod
*** 480,485 ****
--- 612,625 ----
*/
while (extraWaits-- > 0)
PGSemaphoreUnlock(&proc->sem);
+
+ #ifdef LWLOCK_TIMING_STATS
+ /* record end of wait time and start of hold time */
+ INSTR_TIME_SET_CURRENT( lwlock_stats[lockid].th );
+
+ if (mode == LW_EXCLUSIVE) INSTR_TIME_ACCUM_DIFF( lwlock_stats[lockid].time_waited_exclusive, lwlock_stats[lockid].th, lwlock_stats[lockid].ta );
+ else INSTR_TIME_ACCUM_DIFF( lwlock_stats[lockid].time_waited_share, lwlock_stats[lockid].th, lwlock_stats[lockid].ta );
+ #endif
}
/*
*************** LWLockConditionalAcquire(LWLockId lockid
*** 548,553 ****
--- 688,707 ----
/* Add lock to list of locks held by this backend */
held_lwlocks[num_held_lwlocks++] = lockid;
TRACE_POSTGRESQL_LWLOCK_CONDACQUIRE(lockid, mode);
+
+ #ifdef LWLOCK_STATS
+ /* Set up local count state first time through in a given process */
+ if (counts_for_pid != MyProcPid)
+ lock_stats_setup();
+
+ /* Count lock acquisition attempts */
+ if (mode == LW_EXCLUSIVE) lwlock_stats[lockid].count_acquired_exclusive++;
+ else lwlock_stats[lockid].count_acquired_share++;
+ #ifdef LWLOCK_TIMING_STATS
+ /* record start of hold time */
+ INSTR_TIME_SET_CURRENT( lwlock_stats[lockid].th );
+ #endif
+ #endif /* LWLOCK_STATS */
}
return !mustwait;
*************** LWLockRelease(LWLockId lockid)
*** 563,568 ****
--- 717,725 ----
PGPROC *head;
PGPROC *proc;
int i;
+ #ifdef LWLOCK_TIMING_STATS
+ bool was_exclusive = false;
+ #endif
PRINT_LWDEBUG("LWLockRelease", lockid, lock);
*************** LWLockRelease(LWLockId lockid)
*** 586,592 ****
--- 743,754 ----
/* Release my hold on lock */
if (lock->exclusive > 0)
+ {
lock->exclusive--;
+ #ifdef LWLOCK_TIMING_STATS
+ was_exclusive = true;
+ #endif
+ }
else
{
Assert(lock->shared > 0);
*************** LWLockRelease(LWLockId lockid)
*** 651,656 ****
--- 813,825 ----
* Now okay to allow cancel/die interrupts.
*/
RESUME_INTERRUPTS();
+ #ifdef LWLOCK_TIMING_STATS
+ /* record end of hold time */
+ INSTR_TIME_SET_CURRENT( lwlock_stats[lockid].ta );
+
+ if (was_exclusive) INSTR_TIME_ACCUM_DIFF( lwlock_stats[lockid].time_held_exclusive, lwlock_stats[lockid].ta, lwlock_stats[lockid].th );
+ else INSTR_TIME_ACCUM_DIFF( lwlock_stats[lockid].time_held_share, lwlock_stats[lockid].ta, lwlock_stats[lockid].th );
+ #endif
}