Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/usr.sbin/tprof add accumulative mode. "tprof top -a"
details: https://anonhg.NetBSD.org/src/rev/aee5ce392b42
branches: trunk
changeset: 372566:aee5ce392b42
user: ryo <ryo%NetBSD.org@localhost>
date: Fri Dec 09 01:55:46 2022 +0000
description:
add accumulative mode. "tprof top -a"
diffstat:
usr.sbin/tprof/tprof.8 | 15 +-
usr.sbin/tprof/tprof_top.c | 453 ++++++++++++++++++++++++++++----------------
2 files changed, 298 insertions(+), 170 deletions(-)
diffs (truncated from 769 to 300 lines):
diff -r ef9a9fc1a468 -r aee5ce392b42 usr.sbin/tprof/tprof.8
--- a/usr.sbin/tprof/tprof.8 Fri Dec 09 00:35:58 2022 +0000
+++ b/usr.sbin/tprof/tprof.8 Fri Dec 09 01:55:46 2022 +0000
@@ -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 @@
.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 @@
.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 @@
.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
diff -r ef9a9fc1a468 -r aee5ce392b42 usr.sbin/tprof/tprof_top.c
--- a/usr.sbin/tprof/tprof_top.c Fri Dec 09 00:35:58 2022 +0000
+++ b/usr.sbin/tprof/tprof_top.c Fri Dec 09 01:55:46 2022 +0000
@@ -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 <ryo%nerv.org@localhost>
@@ -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 @@
#include <sys/ioctl.h>
#include <sys/time.h>
-#include <assert.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
@@ -54,14 +53,79 @@
#include "tprof.h"
#include "ksyms.h"
+#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 sig_atomic_t sigalrm;
-static struct winsize win;
-static long top_interval = 1;
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 = 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;
+
+ 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 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;
+static void
+ptrarray_iterate(struct ptrarray *ptrarray, void (*ifunc)(void *))
+{
+ size_t i;
-static int opt_userland = 0;
-static int opt_showcounter = 0;
+ 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 @@
.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_clear_instantaneous(void *arg)
+{
+ struct sample_elm *e = (void *)arg;
+
+ e->num[SAMPLE_MODE_INSTANTANEOUS] = 0;
+ memset(SAMPLE_ELM_NUM_CPU(e, SAMPLE_MODE_INSTANTANEOUS),
+ 0, sizeof(e->num_cpu[0]) * ncpu);
}
static void
-sample_reset(void)
+sample_reset(bool reset_accumulative)
{
- 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);
+ int mode;
+
+ 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);
}
- 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);
Home |
Main Index |
Thread Index |
Old Index