Module Name: src
Committed By: ryo
Date: Fri Dec 9 01:55:46 UTC 2022
Modified Files:
src/usr.sbin/tprof: tprof.8 tprof_top.c
Log Message:
add accumulative mode. "tprof top -a"
To generate a diff of this commit:
cvs rdiff -u -r1.19 -r1.20 src/usr.sbin/tprof/tprof.8
cvs rdiff -u -r1.2 -r1.3 src/usr.sbin/tprof/tprof_top.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/usr.sbin/tprof/tprof.8
diff -u src/usr.sbin/tprof/tprof.8:1.19 src/usr.sbin/tprof/tprof.8:1.20
--- src/usr.sbin/tprof/tprof.8:1.19 Thu Dec 1 00:43:27 2022
+++ src/usr.sbin/tprof/tprof.8 Fri Dec 9 01:55:46 2022
@@ -1,4 +1,4 @@
-.\" $NetBSD: tprof.8,v 1.19 2022/12/01 00:43:27 ryo Exp $
+.\" $NetBSD: tprof.8,v 1.20 2022/12/09 01:55:46 ryo Exp $
.\"
.\" Copyright (c)2011 YAMAMOTO Takashi,
.\" All rights reserved.
@@ -24,7 +24,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd December 1, 2022
+.Dd December 9, 2022
.Dt TPROF 8
.Os
.Sh NAME
@@ -137,8 +137,7 @@ Per symbol.
.Op Fl e Ar ...
.Oc
.Op Fl i Ar interval
-.Op Fl c
-.Op Fl u
+.Op Fl acu
.Xc
Displays profiling results in real-time.
.Ar name
@@ -158,6 +157,10 @@ is specified, profiling is performed eve
.Bl -tag -width XXintervalX -offset indent
.It Fl i Ar interval
set the update interval in seconds. The default value is 1.
+.It Fl a
+Starts in accumulation mode. The display is updated every
+.Ar interval
+second, but the values are accumulative.
.It Fl c
show the delta of the event counters.
.It Fl u
@@ -226,7 +229,9 @@ utility was written by
.An YAMAMOTO Takashi .
It was revamped by
.An Maxime Villard
-in 2018.
+in 2018, and by
+.An Ryo Shimizu
+in 2022.
.Sh CAVEATS
The contents and representation of recorded samples are undocumented and
will likely be changed for future releases of
Index: src/usr.sbin/tprof/tprof_top.c
diff -u src/usr.sbin/tprof/tprof_top.c:1.2 src/usr.sbin/tprof/tprof_top.c:1.3
--- src/usr.sbin/tprof/tprof_top.c:1.2 Thu Dec 1 03:32:24 2022
+++ src/usr.sbin/tprof/tprof_top.c Fri Dec 9 01:55:46 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: tprof_top.c,v 1.2 2022/12/01 03:32:24 ryo Exp $ */
+/* $NetBSD: tprof_top.c,v 1.3 2022/12/09 01:55:46 ryo Exp $ */
/*-
* Copyright (c) 2022 Ryo Shimizu <[email protected]>
@@ -28,7 +28,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: tprof_top.c,v 1.2 2022/12/01 03:32:24 ryo Exp $");
+__RCSID("$NetBSD: tprof_top.c,v 1.3 2022/12/09 01:55:46 ryo Exp $");
#endif /* not lint */
#include <sys/param.h>
@@ -37,7 +37,6 @@ __RCSID("$NetBSD: tprof_top.c,v 1.2 2022
#include <sys/ioctl.h>
#include <sys/time.h>
-#include <assert.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
@@ -54,14 +53,79 @@ __RCSID("$NetBSD: tprof_top.c,v 1.2 2022
#include "tprof.h"
#include "ksyms.h"
-static struct sym **ksyms;
-static size_t nksyms;
-static sig_atomic_t sigalrm;
+#define SAMPLE_MODE_ACCUMULATIVE 0
+#define SAMPLE_MODE_INSTANTANEOUS 1
+#define SAMPLE_MODE_NUM 2
+
+struct sample_elm {
+ struct rb_node node;
+ uint64_t addr;
+ const char *name;
+ uint32_t flags;
+#define SAMPLE_ELM_FLAGS_USER 0x00000001
+ uint32_t num[SAMPLE_MODE_NUM];
+ uint32_t num_cpu[]; /* [SAMPLE_MODE_NUM][ncpu] */
+#define SAMPLE_ELM_NUM_CPU(e, k) \
+ ((e)->num_cpu + (k) * ncpu)
+};
+
+struct ptrarray {
+ void **pa_ptrs;
+ size_t pa_allocnum;
+ size_t pa_inuse;
+};
+
+static int opt_mode = SAMPLE_MODE_INSTANTANEOUS;
+static int opt_userland = 0;
+static int opt_showcounter = 0;
+
+/* for display */
static struct winsize win;
+static int nontty;
static long top_interval = 1;
+
+/* for profiling and counting samples */
+static sig_atomic_t sigalrm;
+static struct sym **ksyms;
+static size_t nksyms;
static u_int nevent;
static const char *eventname[TPROF_MAXCOUNTERS];
-static int nontty;
+static size_t sizeof_sample_elm;
+static rb_tree_t rb_tree_sample;
+struct ptrarray sample_list[SAMPLE_MODE_NUM];
+static u_int sample_n_kern[SAMPLE_MODE_NUM];
+static u_int sample_n_user[SAMPLE_MODE_NUM];
+static uint32_t *sample_n_kern_per_cpu[SAMPLE_MODE_NUM]; /* [ncpu] */
+static uint32_t *sample_n_user_per_cpu[SAMPLE_MODE_NUM]; /* [ncpu] */
+static uint64_t *sample_n_per_event[SAMPLE_MODE_NUM]; /* [nevent] */
+static uint64_t *sample_n_per_event_cpu[SAMPLE_MODE_NUM]; /* [ncpu] */
+
+/* raw event counter */
+static uint64_t *counters; /* counters[2][ncpu][nevent] */
+static u_int counters_i;
+
+static const char *
+cycle_event_name(void)
+{
+ const char *cycleevent;
+
+ switch (tprof_info.ti_ident) {
+ case TPROF_IDENT_INTEL_GENERIC:
+ cycleevent = "unhalted-core-cycles";
+ break;
+ case TPROF_IDENT_AMD_GENERIC:
+ cycleevent = "LsNotHaltedCyc";
+ break;
+ case TPROF_IDENT_ARMV8_GENERIC:
+ case TPROF_IDENT_ARMV7_GENERIC:
+ cycleevent = "CPU_CYCLES";
+ break;
+ default:
+ cycleevent = NULL;
+ break;
+ }
+ return cycleevent;
+}
/* XXX: use terminfo or curses */
static void
@@ -108,31 +172,37 @@ sigalrm_handler(int signo)
sigalrm = 1;
}
-struct sample_elm {
- struct rb_node node;
- uint64_t addr;
- const char *name;
- uint32_t flags;
-#define SAMPLE_ELM_FLAGS_USER 0x00000001
- uint32_t num;
- uint32_t numcpu[];
-};
+static void
+ptrarray_push(struct ptrarray *ptrarray, void *ptr)
+{
+ int error;
-static size_t sizeof_sample_elm;
-static rb_tree_t rb_tree_sample;
-static char *samplebuf;
-static u_int sample_nused;
-static u_int sample_kern_nsample;
-static u_int sample_user_nsample;
-static u_int sample_max = 1024 * 512; /* XXX */
-static uint32_t *sample_nsample_kern_per_cpu;
-static uint32_t *sample_nsample_user_per_cpu;
-static uint64_t *sample_nsample_per_event;
-static uint64_t *sample_nsample_per_event_cpu;
-static uint64_t collect_overflow;
+ if (ptrarray->pa_inuse >= ptrarray->pa_allocnum) {
+ /* increase buffer */
+ ptrarray->pa_allocnum += 1024;
+ error = reallocarr(&ptrarray->pa_ptrs, ptrarray->pa_allocnum,
+ sizeof(*ptrarray->pa_ptrs));
+ if (error != 0)
+ errc(EXIT_FAILURE, error, "rellocarr failed");
+ }
+ ptrarray->pa_ptrs[ptrarray->pa_inuse++] = ptr;
+}
-static int opt_userland = 0;
-static int opt_showcounter = 0;
+static void
+ptrarray_iterate(struct ptrarray *ptrarray, void (*ifunc)(void *))
+{
+ size_t i;
+
+ for (i = 0; i < ptrarray->pa_inuse; i++) {
+ (*ifunc)(ptrarray->pa_ptrs[i]);
+ }
+}
+
+static void
+ptrarray_clear(struct ptrarray *ptrarray)
+{
+ ptrarray->pa_inuse = 0;
+}
static int
sample_compare_key(void *ctx, const void *n1, const void *keyp)
@@ -154,70 +224,111 @@ static const rb_tree_ops_t sample_ops =
.rbto_compare_key = sample_compare_key
};
+static u_int
+n_align(u_int n, u_int align)
+{
+ return (n + align - 1) / align * align;
+}
+
static void
sample_init(void)
{
- sizeof_sample_elm = sizeof(struct sample_elm) + sizeof(uint32_t) * ncpu;
+ const struct sample_elm *e;
+ int mode;
+
+ u_int size = sizeof(struct sample_elm) +
+ sizeof(e->num_cpu[0]) * SAMPLE_MODE_NUM * ncpu;
+ sizeof_sample_elm = n_align(size, __alignof(struct sample_elm));
+
+ for (mode = 0; mode < SAMPLE_MODE_NUM; mode++) {
+ sample_n_kern_per_cpu[mode] = ecalloc(1,
+ sizeof(typeof(*sample_n_kern_per_cpu[mode])) * ncpu);
+ sample_n_user_per_cpu[mode] = ecalloc(1,
+ sizeof(typeof(*sample_n_user_per_cpu[mode])) * ncpu);
+ sample_n_per_event[mode] = ecalloc(1,
+ sizeof(typeof(*sample_n_per_event[mode])) * nevent);
+ sample_n_per_event_cpu[mode] = ecalloc(1,
+ sizeof(typeof(*sample_n_per_event_cpu[mode])) *
+ nevent * ncpu);
+ }
}
static void
-sample_reset(void)
+sample_clear_instantaneous(void *arg)
{
- if (samplebuf == NULL) {
- samplebuf = emalloc(sizeof_sample_elm * sample_max);
- sample_nsample_kern_per_cpu = emalloc(sizeof(uint32_t) * ncpu);
- sample_nsample_user_per_cpu = emalloc(sizeof(uint32_t) * ncpu);
- sample_nsample_per_event = emalloc(sizeof(uint64_t) * nevent);
- sample_nsample_per_event_cpu =
- emalloc(sizeof(uint64_t) * nevent * ncpu);
- }
- sample_nused = 0;
- sample_kern_nsample = 0;
- sample_user_nsample = 0;
- memset(sample_nsample_kern_per_cpu, 0, sizeof(uint32_t) * ncpu);
- memset(sample_nsample_user_per_cpu, 0, sizeof(uint32_t) * ncpu);
- memset(sample_nsample_per_event, 0, sizeof(uint64_t) * nevent);
- memset(sample_nsample_per_event_cpu, 0,
- sizeof(uint64_t) * nevent * ncpu);
+ struct sample_elm *e = (void *)arg;
- rb_tree_init(&rb_tree_sample, &sample_ops);
+ e->num[SAMPLE_MODE_INSTANTANEOUS] = 0;
+ memset(SAMPLE_ELM_NUM_CPU(e, SAMPLE_MODE_INSTANTANEOUS),
+ 0, sizeof(e->num_cpu[0]) * ncpu);
}
-static struct sample_elm *
-sample_alloc(void)
+static void
+sample_reset(bool reset_accumulative)
{
- struct sample_elm *e;
+ int mode;
- if (sample_nused >= sample_max) {
- errx(EXIT_FAILURE, "sample buffer overflow");
- return NULL;
+ for (mode = 0; mode < SAMPLE_MODE_NUM; mode++) {
+ if (mode == SAMPLE_MODE_ACCUMULATIVE && !reset_accumulative)
+ continue;
+
+ sample_n_kern[mode] = 0;
+ sample_n_user[mode] = 0;
+ memset(sample_n_kern_per_cpu[mode], 0,
+ sizeof(typeof(*sample_n_kern_per_cpu[mode])) * ncpu);
+ memset(sample_n_user_per_cpu[mode], 0,
+ sizeof(typeof(*sample_n_user_per_cpu[mode])) * ncpu);
+ memset(sample_n_per_event[mode], 0,
+ sizeof(typeof(*sample_n_per_event[mode])) * nevent);
+ memset(sample_n_per_event_cpu[mode], 0,
+ sizeof(typeof(*sample_n_per_event_cpu[mode])) *
+ nevent * ncpu);
}
- e = (struct sample_elm *)(samplebuf + sizeof_sample_elm *
- sample_nused++);
- memset(e, 0, sizeof_sample_elm);
- return e;
+ if (reset_accumulative) {
+ rb_tree_init(&rb_tree_sample, &sample_ops);
+ ptrarray_iterate(&sample_list[SAMPLE_MODE_ACCUMULATIVE], free);
+ ptrarray_clear(&sample_list[SAMPLE_MODE_ACCUMULATIVE]);
+ ptrarray_clear(&sample_list[SAMPLE_MODE_INSTANTANEOUS]);
+ } else {
+ ptrarray_iterate(&sample_list[SAMPLE_MODE_INSTANTANEOUS],
+ sample_clear_instantaneous);
+ ptrarray_clear(&sample_list[SAMPLE_MODE_INSTANTANEOUS]);
+ }
}
-static void
-sample_takeback(struct sample_elm *e)
+static int __unused
+sample_sortfunc_accumulative(const void *a, const void *b)
{
- assert(sample_nused > 0);
- sample_nused--;
+ struct sample_elm * const *ea = a;
+ struct sample_elm * const *eb = b;
+ return (*eb)->num[SAMPLE_MODE_ACCUMULATIVE] -
+ (*ea)->num[SAMPLE_MODE_ACCUMULATIVE];
}
static int
-sample_sortfunc(const void *a, const void *b)
+sample_sortfunc_instantaneous(const void *a, const void *b)
{
- const struct sample_elm *ea = a;
- const struct sample_elm *eb = b;
- return eb->num - ea->num;
+ struct sample_elm * const *ea = a;
+ struct sample_elm * const *eb = b;
+ return (*eb)->num[SAMPLE_MODE_INSTANTANEOUS] -
+ (*ea)->num[SAMPLE_MODE_INSTANTANEOUS];
}
static void
-sample_sort(void)
+sample_sort_accumulative(void)
{
- qsort(samplebuf, sample_nused, sizeof_sample_elm, sample_sortfunc);
+ qsort(sample_list[SAMPLE_MODE_ACCUMULATIVE].pa_ptrs,
+ sample_list[SAMPLE_MODE_ACCUMULATIVE].pa_inuse,
+ sizeof(struct sample_elm *), sample_sortfunc_accumulative);
+}
+
+static void
+sample_sort_instantaneous(void)
+{
+ qsort(sample_list[SAMPLE_MODE_INSTANTANEOUS].pa_ptrs,
+ sample_list[SAMPLE_MODE_INSTANTANEOUS].pa_inuse,
+ sizeof(struct sample_elm *), sample_sortfunc_instantaneous);
}
static void
@@ -229,16 +340,24 @@ sample_collect(tprof_sample_t *s)
uint64_t addr, offset;
uint32_t flags = 0;
uint32_t eventid, cpuid;
+ int mode;
eventid = __SHIFTOUT(s->s_flags, TPROF_SAMPLE_COUNTER_MASK);
cpuid = s->s_cpuid;
- sample_nsample_per_event[eventid]++;
- sample_nsample_per_event_cpu[nevent * cpuid + eventid]++;
+ if (eventid >= nevent) /* unknown event from tprof? */
+ return;
+
+ for (mode = 0; mode < SAMPLE_MODE_NUM; mode++) {
+ sample_n_per_event[mode][eventid]++;
+ sample_n_per_event_cpu[mode][nevent * cpuid + eventid]++;
+ }
if ((s->s_flags & TPROF_SAMPLE_INKERNEL) == 0) {
- sample_user_nsample++;
- sample_nsample_user_per_cpu[cpuid]++;
+ sample_n_user[SAMPLE_MODE_ACCUMULATIVE]++;
+ sample_n_user[SAMPLE_MODE_INSTANTANEOUS]++;
+ sample_n_user_per_cpu[SAMPLE_MODE_ACCUMULATIVE][cpuid]++;
+ sample_n_user_per_cpu[SAMPLE_MODE_INSTANTANEOUS][cpuid]++;
name = NULL;
addr = s->s_pid; /* XXX */
@@ -247,8 +366,10 @@ sample_collect(tprof_sample_t *s)
if (!opt_userland)
return;
} else {
- sample_kern_nsample++;
- sample_nsample_kern_per_cpu[cpuid]++;
+ sample_n_kern[SAMPLE_MODE_ACCUMULATIVE]++;
+ sample_n_kern[SAMPLE_MODE_INSTANTANEOUS]++;
+ sample_n_kern_per_cpu[SAMPLE_MODE_ACCUMULATIVE][cpuid]++;
+ sample_n_kern_per_cpu[SAMPLE_MODE_INSTANTANEOUS][cpuid]++;
name = ksymlookup(s->s_pc, &offset, &symid);
if (name != NULL) {
@@ -258,24 +379,31 @@ sample_collect(tprof_sample_t *s)
}
}
- e = sample_alloc();
- if (e == NULL) {
- fprintf(stderr, "cannot allocate sample\n");
- collect_overflow++;
- return;
- }
-
+ e = ecalloc(1, sizeof_sample_elm);
e->addr = addr;
e->name = name;
e->flags = flags;
- e->num = 1;
- e->numcpu[cpuid] = 1;
+ e->num[SAMPLE_MODE_ACCUMULATIVE] = 1;
+ e->num[SAMPLE_MODE_INSTANTANEOUS] = 1;
+ SAMPLE_ELM_NUM_CPU(e, SAMPLE_MODE_ACCUMULATIVE)[cpuid] = 1;
+ SAMPLE_ELM_NUM_CPU(e, SAMPLE_MODE_INSTANTANEOUS)[cpuid] = 1;
o = rb_tree_insert_node(&rb_tree_sample, e);
- if (o != e) {
+ if (o == e) {
+ /* new symbol. add to list for sort */
+ ptrarray_push(&sample_list[SAMPLE_MODE_ACCUMULATIVE], o);
+ ptrarray_push(&sample_list[SAMPLE_MODE_INSTANTANEOUS], o);
+ } else {
/* already exists */
- sample_takeback(e);
- o->num++;
- o->numcpu[cpuid]++;
+ free(e);
+
+ o->num[SAMPLE_MODE_ACCUMULATIVE]++;
+ if (o->num[SAMPLE_MODE_INSTANTANEOUS]++ == 0) {
+ /* new instantaneous symbols. add to list for sort */
+ ptrarray_push(&sample_list[SAMPLE_MODE_INSTANTANEOUS],
+ o);
+ }
+ SAMPLE_ELM_NUM_CPU(o, SAMPLE_MODE_ACCUMULATIVE)[cpuid]++;
+ SAMPLE_ELM_NUM_CPU(o, SAMPLE_MODE_INSTANTANEOUS)[cpuid]++;
}
}
@@ -317,16 +445,11 @@ show_timestamp(void)
printf("%-8.8s", &(ctime((time_t *)&tv.tv_sec)[11]));
}
-
-static uint64_t *counters; /* counters[2][ncpu][nevent] */
-static u_int counters_i;
-
static void
show_counters_alloc(void)
{
- size_t sz = 2 * ncpu * nevent * sizeof(uint64_t);
- counters = emalloc(sz);
- memset(counters, 0, sz);
+ size_t sz = 2 * ncpu * nevent * sizeof(*counters);
+ counters = ecalloc(1, sz);
}
static void
@@ -377,22 +500,22 @@ show_count_per_event(void)
u_int i, nsample_total;
int n;
- nsample_total = sample_kern_nsample + sample_user_nsample;
+ nsample_total = sample_n_kern[opt_mode] + sample_n_user[opt_mode];
for (i = 0; i < nevent; i++) {
- if (sample_nsample_per_event[i] >= nsample_total) {
- printf("%5.1f%%", sample_nsample_per_event[i] *
+ if (sample_n_per_event[opt_mode][i] >= nsample_total) {
+ printf("%5.1f%%", sample_n_per_event[opt_mode][i] *
100.00 / nsample_total);
} else {
- printf("%5.2f%%", sample_nsample_per_event[i] *
+ printf("%5.2f%%", sample_n_per_event[opt_mode][i] *
100.00 / nsample_total);
}
- printf("%8"PRIu64" ", sample_nsample_per_event[i]);
+ printf("%8"PRIu64" ", sample_n_per_event[opt_mode][i]);
printf("%-32.32s", eventname[i]);
for (n = 0; n < ncpu; n++) {
printf("%6"PRIu64,
- sample_nsample_per_event_cpu[nevent * n + i]);
+ sample_n_per_event_cpu[opt_mode][nevent * n + i]);
}
printf("\n");
}
@@ -404,6 +527,7 @@ sample_show(void)
static u_int nshow;
struct sample_elm *e;
+ struct ptrarray *samples;
u_int nsample_total;
int i, n, ndisp;
char namebuf[32];
@@ -413,12 +537,18 @@ sample_show(void)
margin_lines += 3 + nevent; /* show_counter_per_event() */
+ if (opt_mode == SAMPLE_MODE_INSTANTANEOUS)
+ sample_sort_instantaneous();
+ else
+ sample_sort_accumulative();
+ samples = &sample_list[opt_mode];
+
if (opt_showcounter)
margin_lines += 2 + nevent;
if (opt_userland)
margin_lines += 1;
- ndisp = sample_nused;
+ ndisp = samples->pa_inuse;
if (!nontty && ndisp > (win.ws_row - margin_lines))
ndisp = win.ws_row - margin_lines;
@@ -427,6 +557,9 @@ sample_show(void)
cls_eos();
+ if (opt_mode == SAMPLE_MODE_ACCUMULATIVE)
+ printf("[Accumulative mode] ");
+
show_tprof_stat();
cls_eol();
@@ -477,22 +610,22 @@ sample_show(void)
printf("\n");
for (i = 0; i < ndisp; i++) {
- e = (struct sample_elm *)(samplebuf + sizeof_sample_elm * i);
+ e = (struct sample_elm *)samples->pa_ptrs[i];
name = e->name;
if (name == NULL) {
if (e->flags & SAMPLE_ELM_FLAGS_USER) {
- snprintf(namebuf, sizeof(namebuf), "<PID:%"PRIu64">",
- e->addr);
+ snprintf(namebuf, sizeof(namebuf),
+ "<PID:%"PRIu64">", e->addr);
} else {
- snprintf(namebuf, sizeof(namebuf), "0x%016"PRIx64,
- e->addr);
+ snprintf(namebuf, sizeof(namebuf),
+ "0x%016"PRIx64, e->addr);
}
name = namebuf;
}
- nsample_total = sample_kern_nsample;
+ nsample_total = sample_n_kern[opt_mode];
if (opt_userland)
- nsample_total += sample_user_nsample;
+ nsample_total += sample_n_user[opt_mode];
/*
* even when only kernel mode events are configured,
* interrupts may still occur in the user mode state.
@@ -500,25 +633,29 @@ sample_show(void)
if (nsample_total == 0)
nsample_total = 1;
- if (e->num >= nsample_total) {
- printf("%5.1f%%", e->num * 100.00 / nsample_total);
+ if (e->num[opt_mode] >= nsample_total) {
+ printf("%5.1f%%",
+ e->num[opt_mode] * 100.00 / nsample_total);
} else {
- printf("%5.2f%%", e->num * 100.00 / nsample_total);
+ printf("%5.2f%%",
+ e->num[opt_mode] * 100.00 / nsample_total);
}
- printf("%8u %-32.32s", e->num, name);
+ printf("%8u %-32.32s", e->num[opt_mode], name);
for (n = 0; n < ncpu; n++) {
- if (e->numcpu[n] == 0)
+ if (SAMPLE_ELM_NUM_CPU(e, opt_mode)[n] == 0) {
printf(" .");
- else
- printf("%6u", e->numcpu[n]);
+ } else {
+ printf("%6u",
+ SAMPLE_ELM_NUM_CPU(e, opt_mode)[n]);
+ }
}
printf("\n");
}
- if ((u_int)ndisp != sample_nused) {
- printf(" : : (more %u symbols omitted)\n",
- sample_nused - ndisp);
+ if ((u_int)ndisp != samples->pa_inuse) {
+ printf(" : : (more %zu symbols omitted)\n",
+ samples->pa_inuse - ndisp);
} else {
for (i = ndisp; i <= win.ws_row - margin_lines; i++) {
printf("~");
@@ -534,16 +671,17 @@ sample_show(void)
}
printf("\n");
- printf("Total %8u %-32.32s", sample_kern_nsample, "in-kernel");
+ printf("Total %8u %-32.32s", sample_n_kern[opt_mode], "in-kernel");
for (n = 0; n < ncpu; n++) {
- printf("%6u", sample_nsample_kern_per_cpu[n]);
+ printf("%6u", sample_n_kern_per_cpu[opt_mode][n]);
}
if (opt_userland) {
printf("\n");
- printf(" %8u %-32.32s", sample_user_nsample, "userland");
+ printf(" %8u %-32.32s",
+ sample_n_user[opt_mode], "userland");
for (n = 0; n < ncpu; n++) {
- printf("%6u", sample_nsample_user_per_cpu[n]);
+ printf("%6u", sample_n_user_per_cpu[opt_mode][n]);
}
}
@@ -553,8 +691,8 @@ sample_show(void)
__dead static void
tprof_top_usage(void)
{
- fprintf(stderr, "%s top [-e name[,scale] [-e ...]]"
- " [-i interval] [-c] [-u]\n", getprogname());
+ fprintf(stderr, "%s top [-acu] [-e name[,scale] [-e ...]]"
+ " [-i interval]\n", getprogname());
exit(EXIT_FAILURE);
}
@@ -591,16 +729,19 @@ tprof_top(int argc, char **argv)
tprof_param_t params[TPROF_MAXCOUNTERS];
struct sigaction sa;
struct itimerval it;
- ssize_t bufsize;
+ ssize_t tprof_bufsize;
u_int i;
int ch, ret;
- char *buf, *tokens[2], *p;
+ char *tprof_buf, *tokens[2], *p;
memset(params, 0, sizeof(params));
nevent = 0;
- while ((ch = getopt(argc, argv, "ce:i:u")) != -1) {
+ while ((ch = getopt(argc, argv, "ace:i:u")) != -1) {
switch (ch) {
+ case 'a':
+ opt_mode = SAMPLE_MODE_ACCUMULATIVE;
+ break;
case 'c':
opt_showcounter = 1;
break;
@@ -610,8 +751,11 @@ tprof_top(int argc, char **argv)
tokens[1] = strtok(NULL, ",");
tprof_event_lookup(tokens[0], ¶ms[nevent]);
if (tokens[1] != NULL) {
- if (parse_event_scale(¶ms[nevent], tokens[1]) != 0)
- errx(EXIT_FAILURE, "invalid scale: %s", tokens[1]);
+ if (parse_event_scale(¶ms[nevent],
+ tokens[1]) != 0) {
+ errx(EXIT_FAILURE, "invalid scale: %s",
+ tokens[1]);
+ }
}
eventname[nevent] = tokens[0];
nevent++;
@@ -640,29 +784,8 @@ tprof_top(int argc, char **argv)
if (argc != 0)
tprof_top_usage();
- bufsize = sizeof(tprof_sample_t) * 8192;
- buf = emalloc(bufsize);
-
- sample_init();
-
if (nevent == 0) {
- const char *defaultevent;
-
- switch (tprof_info.ti_ident) {
- case TPROF_IDENT_INTEL_GENERIC:
- defaultevent = "unhalted-core-cycles";
- break;
- case TPROF_IDENT_AMD_GENERIC:
- defaultevent = "LsNotHaltedCyc";
- break;
- case TPROF_IDENT_ARMV8_GENERIC:
- case TPROF_IDENT_ARMV7_GENERIC:
- defaultevent = "CPU_CYCLES";
- break;
- default:
- defaultevent = NULL;
- break;
- }
+ const char *defaultevent = cycle_event_name();
if (defaultevent == NULL)
errx(EXIT_FAILURE, "cpu not supported");
@@ -671,6 +794,7 @@ tprof_top(int argc, char **argv)
nevent++;
}
+ sample_init();
show_counters_alloc();
for (i = 0; i < nevent; i++) {
@@ -707,32 +831,31 @@ tprof_top(int argc, char **argv)
it.it_interval.tv_usec = it.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &it, NULL);
- sample_reset();
+ sample_reset(true);
printf("collecting samples...");
fflush(stdout);
+ tprof_bufsize = sizeof(tprof_sample_t) * 8192;
+ tprof_buf = emalloc(tprof_bufsize);
do {
/* continue to accumulate tprof_sample until alarm arrives */
while (sigalrm == 0) {
- ssize_t len = read(devfd, buf, bufsize);
+ ssize_t len = read(devfd, tprof_buf, tprof_bufsize);
if (len == -1 && errno != EINTR)
err(EXIT_FAILURE, "read");
if (len > 0) {
- tprof_sample_t *s = (tprof_sample_t *)buf;
- while (s < (tprof_sample_t *)(buf + len)) {
- sample_collect(s);
- s++;
- }
+ tprof_sample_t *s = (tprof_sample_t *)tprof_buf;
+ while (s < (tprof_sample_t *)(tprof_buf + len))
+ sample_collect(s++);
}
}
sigalrm = 0;
/* update screen */
- sample_sort();
sample_show();
fflush(stdout);
- sample_reset();
+ sample_reset(false);
} while (!nontty);
printf("\n");