libdb/util/dtrace/locktimes.d

160 lines
4.2 KiB
D
Executable file

#!/usr/sbin/dtrace -qs
/*
* Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved.
*
* locktimesid.d - Display lock wait times grouped by filename.
*
* This script graphs the time spent waiting for DB page locks.
*
* The optional integer maxcount parameter directs the script to exit once that
* many page lock waits have been measured.
*
* usage: locktimes.d { -p <pid> | -c "<program> [<args]" } [maxcount]
*
* The result times in nanoseconds are grouped by (filename, pgno, lock_mode).
*
* Static probes used:
* lock-suspend(DBT *lockobj, db_lockmode_t lock_ mode)
* lock-resume(DBT *lockobj, db_lockmode_t mode)
* db-open(char *file, char *db, uint32_t flags, uint8_t fileid[20])
* db-cursor(char *file, char *db, unsigned txnid, unsigned flags,
* uint8_t fileid[20])
*
* The DBT locates the locked object in shared memory. As long as
* application-specific locks are not being used, the DBT points to
* a DB_ILOCK:
* db_pgno_t pgno;
* u_int8_t fileid[20];
* u_int32_t type;
* Type is 1 for handle, 2 for page, 3 for a queue's record number.
* The mode paramteris the enum db_lockmode_t
* notgranted,read,write,wait,iread,iwrite,iwr,read_unc,wwrite
*
* This script may display unexpected results when application-specific
* locks are present.
*
*/
#pragma D option defaultargs
typedef D`uint32_t db_pgno_t;
/* A DBT for the DB API */
typedef struct __db_dbt {
uintptr_t data; /* Key/data */
uint32_t size; /* key/data length */
uint32_t ulen; /* RO: length of user buffer. */
uint32_t dlen; /* RO: get/put record length. */
uint32_t doff; /* RO: get/put record offset. */
uintptr_t app_data;
uint32_t flags;
} DBT;
/* A DBT in shared memory */
/*
* DB fileids are actually uint8_t fileid[20]; in D it is easier to handle them
* as a struct of 5 four-byte integers.
*/
typedef struct fileid
{
uint32_t id1;
uint32_t id2;
uint32_t id3;
uint32_t id4;
uint32_t id5;
} FILEID;
typedef struct __db_ilock {
uint32_t pgno;
FILEID fileid;
uint32_t type;
} DB_ILOCK;
this DBT *dbt;
this DB_ILOCK *ilock;
this FILEID *fileid;
this string filename;
string filenames[unsigned, unsigned, unsigned, unsigned, unsigned];
self int suspend;
dtrace:::BEGIN
{
maxcount = $1 != 0 ? $1 : -1;
lockcount = 0;
printf("DB lock wait times by (file, pgno) for process %d\n", $target);
printf("Interrupt to display summary\n");
modes[0] = "NOTGRANTED";
modes[1] = "READ";
modes[2] = "WRITE";
modes[3] = "WAIT";
modes[4] = "INTENT_WRITE";
modes[5] = "INTENT_READ";
modes[6] = "INTENT_WR";
modes[7] = "READ_UNCOMMITTED";
modes[8] = "WAS_WRITE";
}
/* lock-suspend(DBT *lockobj, int lock_mode) */
bdb$target:::lock-suspend
{
self->suspend = timestamp;
}
/* lock-resume(DBT *lockobj, int lock_mode) */
bdb$target:::lock-resume
/self->suspend > 0/
{
this->duration = timestamp - self->suspend;
self->suspend = 0;
this->dbt = copyin(arg0, sizeof(DBT));
this->ilock = copyin(this->dbt->data, sizeof(DB_ILOCK));
this->filename = filenames[this->ilock->fileid.id1,
this->ilock->fileid.id2, this->ilock->fileid.id3,
this->ilock->fileid.id4, this->ilock->fileid.id5];
@locktimes[this->filename, this->ilock->pgno, modes[arg1]] =
quantize(this->duration);
lockcount++;
}
bdb$target:::lock-resume
/lockcount == maxcount/
{
exit(0);
}
/* db-open(char *file, char *db, uint32_t flags, uint8_t fileid[20])
*
* Watch db-open probes in order to get the fileid -> file name mapping.
*/
bdb$target:::db-open
/arg0 != 0/
{
this->filename = copyinstr(arg0);
this->fileid = (FILEID *) copyin(arg3, 20);
filenames[this->fileid->id1, this->fileid->id2, this->fileid->id3,
this->fileid->id4, this->fileid->id5] = this->filename;
}
/* db-cursor(char *file, char *db, unsigned txnid, unsigned flags, uint8_t fileid[20])
*
* Watch cursor creation probes in order to get the fileid -> file name mapping.
*/
bdb$target:::db-cursor
/arg0 != 0/
{
this->filename = (string) copyinstr(arg0);
this->fileid = (FILEID *) copyin(arg4, 20);
filenames[this->fileid->id1, this->fileid->id2, this->fileid->id3,
this->fileid->id4, this->fileid->id5] = this->filename;
}
dtrace:::END
{
printa("Wait time for file %s page %u %s locks in nanoseconds %@a\n", @locktimes);
}