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
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=248105
@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <sys/mutex.h>
|
#include <sys/mutex.h>
|
||||||
#include <sys/priv.h>
|
#include <sys/priv.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
|
#include <sys/sbuf.h>
|
||||||
#include <sys/sched.h>
|
#include <sys/sched.h>
|
||||||
#include <sys/smp.h>
|
#include <sys/smp.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
@ -64,6 +65,11 @@ __FBSDID("$FreeBSD$");
|
|||||||
#define _UMUTEX_TRY 1
|
#define _UMUTEX_TRY 1
|
||||||
#define _UMUTEX_WAIT 2
|
#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. */
|
/* Priority inheritance mutex info. */
|
||||||
struct umtx_pi {
|
struct umtx_pi {
|
||||||
/* Owner thread */
|
/* Owner thread */
|
||||||
@ -157,8 +163,8 @@ struct umtxq_chain {
|
|||||||
TAILQ_HEAD(,umtx_pi) uc_pi_list;
|
TAILQ_HEAD(,umtx_pi) uc_pi_list;
|
||||||
|
|
||||||
#ifdef UMTX_PROFILING
|
#ifdef UMTX_PROFILING
|
||||||
int length;
|
u_int length;
|
||||||
int max_length;
|
u_int max_length;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -252,6 +258,117 @@ umtx_init_profiling(void)
|
|||||||
"max_length1", CTLFLAG_RD, &umtxq_chains[1][i].max_length, 0, NULL);
|
"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
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
Reference in New Issue
Block a user