diff options
author | Mark Wong <mark@2ndQuadrant.com> | 2019-06-14 20:26:30 +0000 |
---|---|---|
committer | Mark Wong <mark@2ndQuadrant.com> | 2019-07-08 12:07:56 -0700 |
commit | a1ae03b7b681fef428a009ed3c159d69f0603dab (patch) | |
tree | 64a1b0257068ce87f73486b707c5445a496ac7d8 | |
parent | 1d9377c1c6ed915c9be5ef3a93e9e0ccf207e27e (diff) |
Add LOCKS column
The locks column displays a count of database locks per process.
-rw-r--r-- | machine/m_linux.c | 34 | ||||
-rw-r--r-- | machine/m_remote.c | 64 | ||||
-rw-r--r-- | pg.c | 14 | ||||
-rw-r--r-- | pg_top.1.in | 3 |
4 files changed, 101 insertions, 14 deletions
diff --git a/machine/m_linux.c b/machine/m_linux.c index 98cfd15..f6db76d 100644 --- a/machine/m_linux.c +++ b/machine/m_linux.c @@ -84,6 +84,7 @@ struct top_proc unsigned long start_time; unsigned long xtime; unsigned long qtime; + unsigned int locks; double pcpu; /* Data from /proc/<pid>/io. */ @@ -144,19 +145,20 @@ static char *swapnames[NSWAPSTATS + 1] = }; static char fmt_header[] = -" PID X SIZE RES STATE XTIME QTIME %CPU COMMAND"; +" PID X SIZE RES STATE XTIME QTIME %CPU LOCKS COMMAND"; /* these are names given to allowed sorting orders -- first is default */ static char *ordernames[] = { "cpu", "size", "res", "xtime", "qtime", "rchar", "wchar", "syscr", - "syscw", "reads", "writes", "cwrites", "command", NULL + "syscw", "reads", "writes", "cwrites", "locks", "command", NULL }; /* forward definitions for comparison functions */ static int compare_cmd(const void *, const void *); static int compare_cpu(const void *, const void *); static int compare_cwrites(const void *, const void *); +static int compare_locks(const void *, const void *); static int compare_qtime(const void *, const void *); static int compare_rchar(const void *, const void *); static int compare_reads(const void *, const void *); @@ -182,6 +184,7 @@ int (*proc_compares[]) () = compare_reads, compare_writes, compare_cwrites, + compare_locks, compare_cmd, NULL }; @@ -809,6 +812,7 @@ get_process_info(struct system_info * si, update_str(&n->usename, PQgetvalue(pgresult, i, 3)); n->xtime = atol(PQgetvalue(pgresult, i, 4)); n->qtime = atol(PQgetvalue(pgresult, i, 5)); + n->locks = atoi(PQgetvalue(pgresult, i, 6)); total_procs++; process_states[n->pgstate]++; @@ -908,7 +912,7 @@ format_next_process(caddr_t handle) struct top_proc *p = &pgtable[proc_index++]; snprintf(fmt, sizeof(fmt), - "%5d %-8.8s %5s %5s %-6s %5s %5s %5.1f %s", + "%5d %-8.8s %5s %5s %-6s %5s %5s %5.1f %5d %s", p->pid, p->usename, format_k(p->size), @@ -917,6 +921,7 @@ format_next_process(caddr_t handle) format_time(p->xtime), format_time(p->qtime), p->pcpu * 100.0, + p->locks, p->name); /* return the result */ @@ -944,6 +949,7 @@ format_next_process(caddr_t handle) #define ORDERKEY_CWRITES if ((result = p1->cancelled_write_bytes - \ p2->cancelled_write_bytes) == 0) +#define ORDERKEY_LOCKS if ((result = p2->locks - p1->locks) == 0) #define ORDERKEY_MEM if ((result = p2->size - p1->size) == 0) #define ORDERKEY_NAME if ((result = strcmp(p1->name, p2->name)) == 0) #define ORDERKEY_PCTCPU if ((result = (int)(p2->pcpu - p1->pcpu)) == 0) @@ -1015,6 +1021,28 @@ compare_cwrites(const void *v1, const void *v2) return (result); } +/* + * compare_locks - the comparison function for sorting by total locks ancquired + */ + +static int +compare_locks(const void *v1, const void *v2) +{ + struct top_proc *p1 = (struct top_proc *) v1; + struct top_proc *p2 = (struct top_proc *) v2; + int result; + + ORDERKEY_LOCKS + ORDERKEY_QTIME + ORDERKEY_PCTCPU + ORDERKEY_STATE + ORDERKEY_MEM + ORDERKEY_RSSIZE + ; + + return (result); +} + /* compare_qtime - the comparison function for sorting by total cpu qtime */ static int diff --git a/machine/m_remote.c b/machine/m_remote.c index b2a2dfe..7c274bc 100644 --- a/machine/m_remote.c +++ b/machine/m_remote.c @@ -31,26 +31,44 @@ "FROM pg_memusage()" #define QUERY_PROCTAB \ + "WITH lock_activity AS\n" \ + "(\n" \ + " SELECT pid, count(*) AS lock_count\n" \ + " FROM pg_locks\n" \ + " GROUP BY pid\n" \ + ")\n" \ "SELECT a.pid, comm, fullcomm, a.state, utime, stime,\n" \ " starttime, vsize, rss, usename, rchar, wchar,\n" \ " syscr, syscw, reads, writes, cwrites, b.state,\n" \ " extract(EPOCH FROM age(clock_timestamp(),\n" \ " xact_start))::BIGINT,\n" \ " extract(EPOCH FROM age(clock_timestamp(),\n" \ - " query_start))::BIGINT\n" \ + " query_start))::BIGINT,\n" \ + " coalesce(lock_count, 0) AS lock_count\n" \ "FROM pg_proctab() a LEFT OUTER JOIN pg_stat_activity b\n" \ - " ON a.pid = b.pid" + " ON a.pid = b.pid\n" \ + " LEFT OUTER JOIN lock_activity c\n" \ + " ON a.pid = c.pid;" #define QUERY_PROCTAB_QUERY \ + "WITH lock_activity AS\n" \ + "(\n" \ + " SELECT pid, count(*) AS lock_count\n" \ + " FROM pg_locks\n" \ + " GROUP BY pid\n" \ + ")\n" \ "SELECT a.pid, comm, query, a.state, utime, stime,\n" \ " starttime, vsize, rss, usename, rchar, wchar,\n" \ " syscr, syscw, reads, writes, cwrites, b.state,\n" \ " extract(EPOCH FROM age(clock_timestamp(),\n" \ " xact_start))::BIGINT,\n" \ " extract(EPOCH FROM age(clock_timestamp(),\n" \ - " query_start))::BIGINT\n" \ + " query_start))::BIGINT,\n" \ + " coalesce(lock_count, 0) AS lock_count\n" \ "FROM pg_proctab() a LEFT OUTER JOIN pg_stat_activity b\n" \ - " ON a.pid = b.pid" + " ON a.pid = b.pid\n" \ + " LEFT OUTER JOIN lock_activity c\n" \ + " ON a.pid = c.pid;" #define QUERY_PG_PROC \ "SELECT COUNT(*)\n" \ @@ -65,7 +83,7 @@ enum column_memusage { c_memused, c_memfree, c_memshared, c_membuffers, enum column_proctab { c_pid, c_comm, c_fullcomm, c_state, c_utime, c_stime, c_starttime, c_vsize, c_rss, c_username, c_rchar, c_wchar, c_syscr, c_syscw, c_reads, c_writes, c_cwrites, - c_pgstate, c_xtime, c_qtime}; + c_pgstate, c_xtime, c_qtime, c_locks}; #define bytetok(x) (((x) + 512) >> 10) @@ -101,6 +119,7 @@ struct top_proc_r unsigned long start_time; unsigned long xtime; unsigned long qtime; + unsigned int locks; double pcpu; /* The change in the previous values and current values. */ @@ -146,7 +165,7 @@ static char *memorynames[NMEMSTATS + 1] = static char *ordernames[] = { "cpu", "size", "res", "xtime", "qtime", "rchar", "wchar", "syscr", - "syscw", "reads", "writes", "cwrites", "command", NULL + "syscw", "reads", "writes", "cwrites", "locks", "command", NULL }; static char *swapnames[NSWAPSTATS + 1] = @@ -155,7 +174,7 @@ static char *swapnames[NSWAPSTATS + 1] = }; static char fmt_header[] = - " PID X SIZE RES STATE XTIME QTIME %CPU COMMAND"; + " PID X SIZE RES STATE XTIME QTIME %CPU LOCKS COMMAND"; /* Now the array that maps process state to a weight. */ @@ -195,11 +214,13 @@ static int64_t cp_diff[NCPUSTATES]; #define ORDERKEY_CWRITES if ((result = p1->cancelled_write_bytes - p2->cancelled_write_bytes) == 0) #define ORDERKEY_XTIME if ((result = p2->xtime - p1->xtime) == 0) #define ORDERKEY_QTIME if ((result = p2->qtime - p1->qtime) == 0) +#define ORDERKEY_LOCKS if ((result = p2->locks - p1->locks) == 0) int check_for_function(PGconn *, char *); static int compare_cmd_r(const void *, const void *); static int compare_cpu_r(const void *, const void *); static int compare_cwrites_r(const void *, const void *); +static int compare_locks_r(const void *, const void *); static int compare_qtime_r(const void *, const void *); static int compare_rchar_r(const void *, const void *); static int compare_reads_r(const void *, const void *); @@ -252,6 +273,7 @@ int (*proc_compares_r[])() = compare_reads_r, compare_writes_r, compare_cwrites_r, + compare_locks_r, compare_cmd_r, NULL }; @@ -313,6 +335,29 @@ compare_cwrites_r(const void *v1, const void *v2) return (result); } +/* + * compare_locks_r - the comparison function for sorting by total locks + * acquired + */ + +int +compare_locks_r(const void *v1, const void *v2) +{ + struct top_proc_r *p1 = (struct top_proc_r *) v1; + struct top_proc_r *p2 = (struct top_proc_r *) v2; + int result; + + ORDERKEY_LOCKS + ORDERKEY_QTIME + ORDERKEY_PCTCPU + ORDERKEY_STATE + ORDERKEY_MEM + ORDERKEY_RSSIZE + ; + + return (result); +} + /* compare_qtime_r - the comparison function for sorting by total cpu qtime */ static int @@ -559,7 +604,7 @@ format_next_process_r(caddr_t handler) struct top_proc_r *p = &pgrtable[proc_r_index++]; snprintf(fmt, sizeof(fmt), - "%5d %-8.8s %5s %5s %-6s %5s %5s %5.1f %s", + "%5d %-8.8s %5s %5s %-6s %5s %5s %5.1f %5d %s", (int) p->pid, /* Some OS's need to cast pid_t to int. */ p->usename, format_k(p->size), @@ -568,6 +613,7 @@ format_next_process_r(caddr_t handler) format_time(p->xtime), format_time(p->qtime), p->pcpu * 100.0, + p->locks, p->name); return (fmt); @@ -804,6 +850,8 @@ get_process_info_r(struct system_info *si, struct process_select *sel, n->xtime = atol(PQgetvalue(pgresult, i, c_xtime)); n->qtime = atol(PQgetvalue(pgresult, i, c_qtime)); + n->locks = atol(PQgetvalue(pgresult, i, c_locks)); + value = atoll(PQgetvalue(pgresult, i, c_rchar)); n->rchar_diff = value - n->rchar; n->rchar = value; @@ -9,12 +9,20 @@ #include "pg_top.h" #define QUERY_PROCESSES \ - "SELECT pid, query, state, usename,\n" \ + "WITH lock_activity AS\n" \ + "(\n" \ + " SELECT pid, count(*) AS lock_count\n" \ + " FROM pg_locks\n" \ + " GROUP BY pid\n" \ + ")\n" \ + "SELECT a.pid, query, state, usename,\n" \ " extract(EPOCH FROM age(clock_timestamp(),\n" \ " xact_start))::BIGINT,\n" \ " extract(EPOCH FROM age(clock_timestamp(),\n" \ - " query_start))::BIGINT\n" \ - "FROM pg_stat_activity;" + " query_start))::BIGINT,\n" \ + " coalesce(lock_count, 0) AS lock_count\n" \ + "FROM pg_stat_activity a LEFT OUTER JOIN lock_activity b\n" \ + " ON a.pid = b.pid;" #define QUERY_PROCESSES_9_1 \ "SELECT procpid, current_query\n" \ diff --git a/pg_top.1.in b/pg_top.1.in index 16d949c..ea2fc06 100644 --- a/pg_top.1.in +++ b/pg_top.1.in @@ -327,6 +327,9 @@ Elapsed time since the current query started. .B %CPU Percentage of available cpu time used by this process. .TP +.B LOCKS +Number of locks granted to this process. +.TP .B COMMAND Name of the command that the process is currently running. .SH COLOR |