Improve UMTX_PROFILING:
- Use u_int values for length and max_length values - Add a way to reset the max_length heuristic in order to have the possibility to reuse the mechanism consecutively without rebooting the machine - Add a way to quick display top5 contented buckets in the system for the max_length value. This should give a quick overview on the quality of the hash table distribution. Sponsored by: EMC / Isilon storage division Reviewed by: jeff, davide
This commit is contained in:
parent
784bcaa1dc
commit
1fc8c346d5
@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/priv.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/sbuf.h>
|
||||
#include <sys/sched.h>
|
||||
#include <sys/smp.h>
|
||||
#include <sys/sysctl.h>
|
||||
@ -64,6 +65,11 @@ __FBSDID("$FreeBSD$");
|
||||
#define _UMUTEX_TRY 1
|
||||
#define _UMUTEX_WAIT 2
|
||||
|
||||
#ifdef UMTX_PROFILING
|
||||
#define UPROF_PERC_BIGGER(w, f, sw, sf) \
|
||||
(((w) > (sw)) || ((w) == (sw) && (f) > (sf)))
|
||||
#endif
|
||||
|
||||
/* Priority inheritance mutex info. */
|
||||
struct umtx_pi {
|
||||
/* Owner thread */
|
||||
@ -157,8 +163,8 @@ struct umtxq_chain {
|
||||
TAILQ_HEAD(,umtx_pi) uc_pi_list;
|
||||
|
||||
#ifdef UMTX_PROFILING
|
||||
int length;
|
||||
int max_length;
|
||||
u_int length;
|
||||
u_int max_length;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -252,6 +258,117 @@ umtx_init_profiling(void)
|
||||
"max_length1", CTLFLAG_RD, &umtxq_chains[1][i].max_length, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
sysctl_debug_umtx_chains_peaks(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
char buf[512];
|
||||
struct sbuf sb;
|
||||
struct umtxq_chain *uc;
|
||||
u_int fract, i, j, tot, whole;
|
||||
u_int sf0, sf1, sf2, sf3, sf4;
|
||||
u_int si0, si1, si2, si3, si4;
|
||||
u_int sw0, sw1, sw2, sw3, sw4;
|
||||
|
||||
sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN);
|
||||
for (i = 0; i < 2; i++) {
|
||||
tot = 0;
|
||||
for (j = 0; j < UMTX_CHAINS; ++j) {
|
||||
uc = &umtxq_chains[i][j];
|
||||
mtx_lock(&uc->uc_lock);
|
||||
tot += uc->max_length;
|
||||
mtx_unlock(&uc->uc_lock);
|
||||
}
|
||||
if (tot == 0)
|
||||
sbuf_printf(&sb, "%u) Empty ", i);
|
||||
else {
|
||||
sf0 = sf1 = sf2 = sf3 = sf4 = 0;
|
||||
si0 = si1 = si2 = si3 = si4 = 0;
|
||||
sw0 = sw1 = sw2 = sw3 = sw4 = 0;
|
||||
for (j = 0; j < UMTX_CHAINS; j++) {
|
||||
uc = &umtxq_chains[i][j];
|
||||
mtx_lock(&uc->uc_lock);
|
||||
whole = uc->max_length * 100;
|
||||
mtx_unlock(&uc->uc_lock);
|
||||
fract = (whole % tot) * 100;
|
||||
if (UPROF_PERC_BIGGER(whole, fract, sw0, sf0)) {
|
||||
sf0 = fract;
|
||||
si0 = j;
|
||||
sw0 = whole;
|
||||
} else if (UPROF_PERC_BIGGER(whole, fract, sw1,
|
||||
sf1)) {
|
||||
sf1 = fract;
|
||||
si1 = j;
|
||||
sw1 = whole;
|
||||
} else if (UPROF_PERC_BIGGER(whole, fract, sw2,
|
||||
sf2)) {
|
||||
sf2 = fract;
|
||||
si2 = j;
|
||||
sw2 = whole;
|
||||
} else if (UPROF_PERC_BIGGER(whole, fract, sw3,
|
||||
sf3)) {
|
||||
sf3 = fract;
|
||||
si3 = j;
|
||||
sw3 = whole;
|
||||
} else if (UPROF_PERC_BIGGER(whole, fract, sw4,
|
||||
sf4)) {
|
||||
sf4 = fract;
|
||||
si4 = j;
|
||||
sw4 = whole;
|
||||
}
|
||||
}
|
||||
sbuf_printf(&sb, "queue %u:\n", i);
|
||||
sbuf_printf(&sb, "1st: %u.%u%% idx: %u\n", sw0 / tot,
|
||||
sf0 / tot, si0);
|
||||
sbuf_printf(&sb, "2nd: %u.%u%% idx: %u\n", sw1 / tot,
|
||||
sf1 / tot, si1);
|
||||
sbuf_printf(&sb, "3rd: %u.%u%% idx: %u\n", sw2 / tot,
|
||||
sf2 / tot, si2);
|
||||
sbuf_printf(&sb, "4th: %u.%u%% idx: %u\n", sw3 / tot,
|
||||
sf3 / tot, si3);
|
||||
sbuf_printf(&sb, "5th: %u.%u%% idx: %u\n", sw4 / tot,
|
||||
sf4 / tot, si4);
|
||||
}
|
||||
}
|
||||
sbuf_trim(&sb);
|
||||
sbuf_finish(&sb);
|
||||
sysctl_handle_string(oidp, sbuf_data(&sb), sbuf_len(&sb), req);
|
||||
sbuf_delete(&sb);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
sysctl_debug_umtx_chains_clear(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct umtxq_chain *uc;
|
||||
u_int i, j;
|
||||
int clear, error;
|
||||
|
||||
clear = 0;
|
||||
error = sysctl_handle_int(oidp, &clear, 0, req);
|
||||
if (error != 0 || req->newptr == NULL)
|
||||
return (error);
|
||||
|
||||
if (clear != 0) {
|
||||
for (i = 0; i < 2; ++i) {
|
||||
for (j = 0; j < UMTX_CHAINS; ++j) {
|
||||
uc = &umtxq_chains[i][j];
|
||||
mtx_lock(&uc->uc_lock);
|
||||
uc->length = 0;
|
||||
uc->max_length = 0;
|
||||
mtx_unlock(&uc->uc_lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
SYSCTL_PROC(_debug_umtx_chains, OID_AUTO, clear,
|
||||
CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 0,
|
||||
sysctl_debug_umtx_chains_clear, "I", "Clear umtx chains statistics");
|
||||
SYSCTL_PROC(_debug_umtx_chains, OID_AUTO, peaks,
|
||||
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 0,
|
||||
sysctl_debug_umtx_chains_peaks, "A", "Highest peaks in chains max length");
|
||||
#endif
|
||||
|
||||
static void
|
||||
|
Loading…
Reference in New Issue
Block a user