FreeBSD: Optimize large kstat outputs
- Use sbuf_new_for_sysctl() to reduce double-buffering on sysctl output. - Use much faster sbuf_cat() instead of sbuf_printf("%s"). Together it reduces `sysctl kstat.zfs.misc.dbufs` time from minutes to seconds, making dbufstat almost usable. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Alexander Motin <mav@FreeBSD.org> Sponsored by: iXsystems, Inc. Closes #15495
This commit is contained in:
parent
c34fe8dcbc
commit
f13593619b
|
@ -187,19 +187,18 @@ kstat_sysctl_dataset_string(SYSCTL_HANDLER_ARGS)
|
||||||
static int
|
static int
|
||||||
kstat_sysctl_io(SYSCTL_HANDLER_ARGS)
|
kstat_sysctl_io(SYSCTL_HANDLER_ARGS)
|
||||||
{
|
{
|
||||||
struct sbuf *sb;
|
struct sbuf sb;
|
||||||
kstat_t *ksp = arg1;
|
kstat_t *ksp = arg1;
|
||||||
kstat_io_t *kip = ksp->ks_data;
|
kstat_io_t *kip = ksp->ks_data;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
sb = sbuf_new_auto();
|
sbuf_new_for_sysctl(&sb, NULL, 0, req);
|
||||||
if (sb == NULL)
|
|
||||||
return (ENOMEM);
|
|
||||||
/* Update the aggsums before reading */
|
/* Update the aggsums before reading */
|
||||||
(void) ksp->ks_update(ksp, KSTAT_READ);
|
(void) ksp->ks_update(ksp, KSTAT_READ);
|
||||||
|
|
||||||
/* though wlentime & friends are signed, they will never be negative */
|
/* though wlentime & friends are signed, they will never be negative */
|
||||||
sbuf_printf(sb,
|
sbuf_printf(&sb,
|
||||||
"%-8llu %-8llu %-8u %-8u %-8llu %-8llu "
|
"%-8llu %-8llu %-8u %-8u %-8llu %-8llu "
|
||||||
"%-8llu %-8llu %-8llu %-8llu %-8u %-8u\n",
|
"%-8llu %-8llu %-8llu %-8llu %-8u %-8u\n",
|
||||||
kip->nread, kip->nwritten,
|
kip->nread, kip->nwritten,
|
||||||
|
@ -207,25 +206,21 @@ kstat_sysctl_io(SYSCTL_HANDLER_ARGS)
|
||||||
kip->wtime, kip->wlentime, kip->wlastupdate,
|
kip->wtime, kip->wlentime, kip->wlastupdate,
|
||||||
kip->rtime, kip->rlentime, kip->rlastupdate,
|
kip->rtime, kip->rlentime, kip->rlastupdate,
|
||||||
kip->wcnt, kip->rcnt);
|
kip->wcnt, kip->rcnt);
|
||||||
rc = sbuf_finish(sb);
|
rc = sbuf_finish(&sb);
|
||||||
if (rc == 0)
|
sbuf_delete(&sb);
|
||||||
rc = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb));
|
|
||||||
sbuf_delete(sb);
|
|
||||||
return (rc);
|
return (rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
kstat_sysctl_raw(SYSCTL_HANDLER_ARGS)
|
kstat_sysctl_raw(SYSCTL_HANDLER_ARGS)
|
||||||
{
|
{
|
||||||
struct sbuf *sb;
|
struct sbuf sb;
|
||||||
void *data;
|
void *data;
|
||||||
kstat_t *ksp = arg1;
|
kstat_t *ksp = arg1;
|
||||||
void *(*addr_op)(kstat_t *ksp, loff_t index);
|
void *(*addr_op)(kstat_t *ksp, loff_t index);
|
||||||
int n, has_header, rc = 0;
|
int n, has_header, rc = 0;
|
||||||
|
|
||||||
sb = sbuf_new_auto();
|
sbuf_new_for_sysctl(&sb, NULL, PAGE_SIZE, req);
|
||||||
if (sb == NULL)
|
|
||||||
return (ENOMEM);
|
|
||||||
|
|
||||||
if (ksp->ks_raw_ops.addr)
|
if (ksp->ks_raw_ops.addr)
|
||||||
addr_op = ksp->ks_raw_ops.addr;
|
addr_op = ksp->ks_raw_ops.addr;
|
||||||
|
@ -258,8 +253,10 @@ restart_headers:
|
||||||
if (has_header) {
|
if (has_header) {
|
||||||
if (rc == ENOMEM && !kstat_resize_raw(ksp))
|
if (rc == ENOMEM && !kstat_resize_raw(ksp))
|
||||||
goto restart_headers;
|
goto restart_headers;
|
||||||
if (rc == 0)
|
if (rc == 0) {
|
||||||
sbuf_printf(sb, "\n%s", ksp->ks_raw_buf);
|
sbuf_cat(&sb, "\n");
|
||||||
|
sbuf_cat(&sb, ksp->ks_raw_buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((data = addr_op(ksp, n)) != NULL) {
|
while ((data = addr_op(ksp, n)) != NULL) {
|
||||||
|
@ -270,22 +267,19 @@ restart:
|
||||||
if (rc == ENOMEM && !kstat_resize_raw(ksp))
|
if (rc == ENOMEM && !kstat_resize_raw(ksp))
|
||||||
goto restart;
|
goto restart;
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
sbuf_printf(sb, "%s", ksp->ks_raw_buf);
|
sbuf_cat(&sb, ksp->ks_raw_buf);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ASSERT3U(ksp->ks_ndata, ==, 1);
|
ASSERT3U(ksp->ks_ndata, ==, 1);
|
||||||
sbuf_hexdump(sb, ksp->ks_data,
|
sbuf_hexdump(&sb, ksp->ks_data,
|
||||||
ksp->ks_data_size, NULL, 0);
|
ksp->ks_data_size, NULL, 0);
|
||||||
}
|
}
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
free(ksp->ks_raw_buf, M_TEMP);
|
free(ksp->ks_raw_buf, M_TEMP);
|
||||||
mutex_exit(ksp->ks_lock);
|
mutex_exit(ksp->ks_lock);
|
||||||
sbuf_trim(sb);
|
rc = sbuf_finish(&sb);
|
||||||
rc = sbuf_finish(sb);
|
sbuf_delete(&sb);
|
||||||
if (rc == 0)
|
|
||||||
rc = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb));
|
|
||||||
sbuf_delete(sb);
|
|
||||||
return (rc);
|
return (rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue