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