svn commit: r334701 - in head: lib/libpmc share/examples/hwpmc sys/dev/hwpmc sys/sys usr.sbin/pmc usr.sbin/pmcstat
Matt Macy
mmacy at FreeBSD.org
Wed Jun 6 02:48:13 UTC 2018
Author: mmacy
Date: Wed Jun 6 02:48:09 2018
New Revision: 334701
URL: https://svnweb.freebsd.org/changeset/base/334701
Log:
hwpmc: add summary command and further metadata extensions
metadata changes:
- log pmc sample rate with pmcallocate
- log proc flags with thread / process logging
to identify user vs kernel threads
fixes:
- use log cpuid to translate event id to event name
Implement rudimentary summary command to track sample
counts by thread and process name within a pmc log.
% make -j4 buildkernel >& /dev/null &
% sudo pmcstat -S unhalted_core_cycles -S llc-misses -O foo sleep 15
% pmc summary foo
cpu_clk_unhalted.thread_p_any:
idle: 138108207162
clang-6.0: 105336158004
sh: 72340108510
make: 8642012963
kernel: 7754011631
longest_lat_cache.miss:
clang-6.0: 87502625
sh: 40901227
make: 5500165
kernel: 3300099
awk: 2000060
% pmc summary -f ~/foo
idx: 278 name: cpu_clk_unhalted.thread_p_any rate: 2000003
idle: 69054
clang-6.0: 52668
sh: 36170
make: 4321
kernel: 3877
hwpmc: proc(7445): 3319
awk: 1289
xargs: 357
rand_harvestq: 181
mtree: 102
intr: 53
zfskern: 31
usb: 7
pagedaemon: 4
ntpd: 3
syslogd: 1
acpi_thermal: 1
logger: 1
syncer: 1
snmptrapd: 1
sleep: 1
idx: 17 name: longest_lat_cache.miss rate: 100003
clang-6.0: 875
sh: 409
make: 55
kernel: 33
awk: 20
hwpmc: proc(7445): 14
xargs: 9
idle: 8
intr: 3
zfskern: 2
Added:
head/usr.sbin/pmc/cmd_pmc_summary.cc (contents, props changed)
Modified:
head/lib/libpmc/libpmc.c
head/lib/libpmc/libpmc_pmu_util.c (contents, props changed)
head/lib/libpmc/pmc.h
head/lib/libpmc/pmclog.c
head/lib/libpmc/pmclog.h
head/share/examples/hwpmc/overhead.c
head/sys/dev/hwpmc/hwpmc_logging.c
head/sys/dev/hwpmc/hwpmc_mod.c
head/sys/sys/pmc.h
head/sys/sys/pmclog.h
head/usr.sbin/pmc/Makefile (contents, props changed)
head/usr.sbin/pmc/cmd_pmc.h (contents, props changed)
head/usr.sbin/pmc/cmd_pmc_filter.cc
head/usr.sbin/pmc/cmd_pmc_stat.c (contents, props changed)
head/usr.sbin/pmc/pmc.c (contents, props changed)
head/usr.sbin/pmcstat/pmcstat.c
Modified: head/lib/libpmc/libpmc.c
==============================================================================
--- head/lib/libpmc/libpmc.c Wed Jun 6 01:51:05 2018 (r334700)
+++ head/lib/libpmc/libpmc.c Wed Jun 6 02:48:09 2018 (r334701)
@@ -1007,7 +1007,8 @@ pmc_mdep_is_compatible_class(enum pmc_class pc)
int
pmc_allocate(const char *ctrspec, enum pmc_mode mode,
- uint32_t flags, int cpu, pmc_id_t *pmcid)
+ uint32_t flags, int cpu, pmc_id_t *pmcid,
+ uint64_t count)
{
size_t n;
int retval;
@@ -1030,6 +1031,7 @@ pmc_allocate(const char *ctrspec, enum pmc_mode mode,
pmc_config.pm_cpu = cpu;
pmc_config.pm_mode = mode;
pmc_config.pm_flags = flags;
+ pmc_config.pm_count = count;
if (PMC_IS_SAMPLING_MODE(mode))
pmc_config.pm_caps |= PMC_CAP_INTERRUPT;
/*
Modified: head/lib/libpmc/libpmc_pmu_util.c
==============================================================================
--- head/lib/libpmc/libpmc_pmu_util.c Wed Jun 6 01:51:05 2018 (r334700)
+++ head/lib/libpmc/libpmc_pmu_util.c Wed Jun 6 02:48:09 2018 (r334701)
@@ -162,13 +162,13 @@ pmc_pmu_idx_get_by_event(const char *cpuid, const char
}
const char *
-pmc_pmu_event_get_by_idx(int idx)
+pmc_pmu_event_get_by_idx(const char *cpuid, int idx)
{
const struct pmu_events_map *pme;
const struct pmu_event *pe;
int i;
- if ((pme = pmu_events_map_get(NULL)) == NULL)
+ if ((pme = pmu_events_map_get(cpuid)) == NULL)
return (NULL);
for (i = 0, pe = pme->table; (pe->name || pe->desc || pe->event) && i < idx; pe++, i++);
return (pe->name);
@@ -470,7 +470,7 @@ pmc_pmu_pmcallocate(const char *e __unused, struct pmc
}
const char *
-pmc_pmu_event_get_by_idx(int idx __unused)
+pmc_pmu_event_get_by_idx(const char *c __unused, int idx __unused)
{
return (NULL);
}
Modified: head/lib/libpmc/pmc.h
==============================================================================
--- head/lib/libpmc/pmc.h Wed Jun 6 01:51:05 2018 (r334700)
+++ head/lib/libpmc/pmc.h Wed Jun 6 02:48:09 2018 (r334701)
@@ -75,7 +75,7 @@ struct pmc_pmcinfo {
__BEGIN_DECLS
int pmc_allocate(const char *_ctrspec, enum pmc_mode _mode, uint32_t _flags,
- int _cpu, pmc_id_t *_pmcid);
+ int _cpu, pmc_id_t *_pmcid, uint64_t count);
int pmc_attach(pmc_id_t _pmcid, pid_t _pid);
int pmc_capabilities(pmc_id_t _pmc, uint32_t *_caps);
int pmc_configure_logfile(int _fd);
@@ -120,7 +120,7 @@ void pmc_pmu_print_counter_desc_long(const char *);
void pmc_pmu_print_counter_full(const char *);
uint64_t pmc_pmu_sample_rate_get(const char *);
int pmc_pmu_pmcallocate(const char *, struct pmc_op_pmcallocate *);
-const char *pmc_pmu_event_get_by_idx(int idx);
+const char *pmc_pmu_event_get_by_idx(const char *, int idx);
int pmc_pmu_idx_get_by_event(const char*, const char *);
int pmc_pmu_stat_mode(const char ***);
__END_DECLS
Modified: head/lib/libpmc/pmclog.c
==============================================================================
--- head/lib/libpmc/pmclog.c Wed Jun 6 01:51:05 2018 (r334700)
+++ head/lib/libpmc/pmclog.c Wed Jun 6 02:48:09 2018 (r334701)
@@ -328,6 +328,7 @@ pmclog_get_event(void *cookie, char **data, ssize_t *l
PMCLOG_READ32(le,ev->pl_u.pl_i.pl_arch);
PMCLOG_READSTRING(le, ev->pl_u.pl_i.pl_cpuid, PMC_CPUID_LEN);
memcpy(ev->pl_u.pl_i.pl_cpuid, le, PMC_CPUID_LEN);
+ ps->ps_cpuid = strdup(ev->pl_u.pl_i.pl_cpuid);
ps->ps_version = ev->pl_u.pl_i.pl_version;
ps->ps_arch = ev->pl_u.pl_i.pl_arch;
ps->ps_initialized = 1;
@@ -347,8 +348,8 @@ pmclog_get_event(void *cookie, char **data, ssize_t *l
PMCLOG_READ32(le,ev->pl_u.pl_a.pl_pmcid);
PMCLOG_READ32(le,ev->pl_u.pl_a.pl_event);
PMCLOG_READ32(le,ev->pl_u.pl_a.pl_flags);
- PMCLOG_READ32(le,noop);
- ev->pl_u.pl_a.pl_evname = pmc_pmu_event_get_by_idx(ev->pl_u.pl_a.pl_event);
+ PMCLOG_READ64(le,ev->pl_u.pl_a.pl_rate);
+ ev->pl_u.pl_a.pl_evname = pmc_pmu_event_get_by_idx(ps->ps_cpuid, ev->pl_u.pl_a.pl_event);
if (ev->pl_u.pl_a.pl_evname != NULL)
break;
else if ((ev->pl_u.pl_a.pl_evname =
@@ -407,7 +408,7 @@ pmclog_get_event(void *cookie, char **data, ssize_t *l
case PMCLOG_TYPE_THR_CREATE:
PMCLOG_READ32(le,ev->pl_u.pl_tc.pl_tid);
PMCLOG_READ32(le,ev->pl_u.pl_tc.pl_pid);
- PMCLOG_READ32(le,noop);
+ PMCLOG_READ32(le,ev->pl_u.pl_tc.pl_flags);
memcpy(ev->pl_u.pl_tc.pl_tdname, le, MAXCOMLEN+1);
break;
case PMCLOG_TYPE_THR_EXIT:
@@ -415,6 +416,8 @@ pmclog_get_event(void *cookie, char **data, ssize_t *l
break;
case PMCLOG_TYPE_PROC_CREATE:
PMCLOG_READ32(le,ev->pl_u.pl_pc.pl_pid);
+ PMCLOG_READ32(le,ev->pl_u.pl_pc.pl_flags);
+ PMCLOG_READ32(le,noop);
memcpy(ev->pl_u.pl_pc.pl_pcomm, le, MAXCOMLEN+1);
break;
default: /* unknown record type */
@@ -553,6 +556,7 @@ pmclog_open(int fd)
ps->ps_count = 0;
ps->ps_offset = (off_t) 0;
bzero(&ps->ps_saved, sizeof(ps->ps_saved));
+ ps->ps_cpuid = NULL;
ps->ps_svcount = 0;
ps->ps_fd = fd;
ps->ps_data = NULL;
Modified: head/lib/libpmc/pmclog.h
==============================================================================
--- head/lib/libpmc/pmclog.h Wed Jun 6 01:51:05 2018 (r334700)
+++ head/lib/libpmc/pmclog.h Wed Jun 6 02:48:09 2018 (r334701)
@@ -89,15 +89,16 @@ struct pmclog_ev_pcsample {
};
struct pmclog_ev_pmcallocate {
- uint32_t pl_event;
const char * pl_evname;
+ uint64_t pl_rate;
+ uint32_t pl_event;
uint32_t pl_flags;
pmc_id_t pl_pmcid;
};
struct pmclog_ev_pmcallocatedyn {
- uint32_t pl_event;
char pl_evname[PMC_NAME_MAX];
+ uint32_t pl_event;
uint32_t pl_flags;
pmc_id_t pl_pmcid;
};
@@ -122,6 +123,7 @@ struct pmclog_ev_proccsw {
struct pmclog_ev_proccreate {
pid_t pl_pid;
+ uint32_t pl_flags;
char pl_pcomm[MAXCOMLEN+1];
};
@@ -150,6 +152,7 @@ struct pmclog_ev_sysexit {
struct pmclog_ev_threadcreate {
pid_t pl_tid;
pid_t pl_pid;
+ uint32_t pl_flags;
char pl_tdname[MAXCOMLEN+1];
};
@@ -211,6 +214,7 @@ struct pmclog_parse_state {
int ps_fd; /* active fd or -1 */
char *ps_buffer; /* scratch buffer if fd != -1 */
char *ps_data; /* current parse pointer */
+ char *ps_cpuid; /* log cpuid */
size_t ps_len; /* length of buffered data */
};
Modified: head/share/examples/hwpmc/overhead.c
==============================================================================
--- head/share/examples/hwpmc/overhead.c Wed Jun 6 01:51:05 2018 (r334700)
+++ head/share/examples/hwpmc/overhead.c Wed Jun 6 02:48:09 2018 (r334701)
@@ -65,7 +65,7 @@ main(int argc, char **argv)
if (pmc_init() != 0)
err(EX_OSERR, "hwpmc(4) not loaded, kldload or update your kernel");
- if (pmc_allocate(counter_name, PMC_MODE_SC, 0, 0, &pmcid) < 0)
+ if (pmc_allocate(counter_name, PMC_MODE_SC, 0, 0, &pmcid, 64*1024) < 0)
err(EX_OSERR, "failed to allocate %s as a system counter in counting mode",
counter_name);
Modified: head/sys/dev/hwpmc/hwpmc_logging.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_logging.c Wed Jun 6 01:51:05 2018 (r334700)
+++ head/sys/dev/hwpmc/hwpmc_logging.c Wed Jun 6 02:48:09 2018 (r334701)
@@ -194,7 +194,7 @@ CTASSERT(sizeof(struct pmclog_map_in) == PATH_MAX +
CTASSERT(offsetof(struct pmclog_map_in,pl_pathname) ==
4*4 + sizeof(uintfptr_t));
CTASSERT(sizeof(struct pmclog_map_out) == 4*4 + 2*sizeof(uintfptr_t));
-CTASSERT(sizeof(struct pmclog_pmcallocate) == 6*4);
+CTASSERT(sizeof(struct pmclog_pmcallocate) == 8*4);
CTASSERT(sizeof(struct pmclog_pmcattach) == 6*4 + PATH_MAX);
CTASSERT(offsetof(struct pmclog_pmcattach,pl_pathname) == 6*4);
CTASSERT(sizeof(struct pmclog_pmcdetach) == 6*4);
@@ -991,6 +991,7 @@ pmclog_process_pmcallocate(struct pmc *pm)
PMCLOG_EMIT32(pm->pm_id);
PMCLOG_EMIT32(pm->pm_event);
PMCLOG_EMIT32(pm->pm_flags);
+ PMCLOG_EMIT64(pm->pm_sc.pm_reloadcount);
ps = pmc_soft_ev_acquire(pm->pm_event);
if (ps != NULL)
PMCLOG_EMITSTRING(ps->ps_ev.pm_ev_name,PMC_NAME_MAX);
@@ -1004,6 +1005,7 @@ pmclog_process_pmcallocate(struct pmc *pm)
PMCLOG_EMIT32(pm->pm_id);
PMCLOG_EMIT32(pm->pm_event);
PMCLOG_EMIT32(pm->pm_flags);
+ PMCLOG_EMIT64(pm->pm_sc.pm_reloadcount);
PMCLOG_DESPATCH_SYNC(po);
}
}
@@ -1050,11 +1052,15 @@ pmclog_process_proccreate(struct pmc_owner *po, struct
if (sync) {
PMCLOG_RESERVE(po, PROC_CREATE, sizeof(struct pmclog_proccreate));
PMCLOG_EMIT32(p->p_pid);
+ PMCLOG_EMIT32(p->p_flag);
+ PMCLOG_EMIT32(0);
PMCLOG_EMITSTRING(p->p_comm, MAXCOMLEN+1);
PMCLOG_DESPATCH_SYNC(po);
} else {
PMCLOG_RESERVE(po, PROC_CREATE, sizeof(struct pmclog_proccreate));
PMCLOG_EMIT32(p->p_pid);
+ PMCLOG_EMIT32(p->p_flag);
+ PMCLOG_EMIT32(0);
PMCLOG_EMITSTRING(p->p_comm, MAXCOMLEN+1);
PMCLOG_DESPATCH(po);
}
@@ -1163,14 +1169,14 @@ pmclog_process_threadcreate(struct pmc_owner *po, stru
PMCLOG_RESERVE(po, THR_CREATE, sizeof(struct pmclog_threadcreate));
PMCLOG_EMIT32(td->td_tid);
PMCLOG_EMIT32(p->p_pid);
- PMCLOG_EMIT32(0);
+ PMCLOG_EMIT32(p->p_flag);
PMCLOG_EMITSTRING(td->td_name, MAXCOMLEN+1);
PMCLOG_DESPATCH_SYNC(po);
} else {
PMCLOG_RESERVE(po, THR_CREATE, sizeof(struct pmclog_threadcreate));
PMCLOG_EMIT32(td->td_tid);
PMCLOG_EMIT32(p->p_pid);
- PMCLOG_EMIT32(0);
+ PMCLOG_EMIT32(p->p_flag);
PMCLOG_EMITSTRING(td->td_name, MAXCOMLEN+1);
PMCLOG_DESPATCH(po);
}
Modified: head/sys/dev/hwpmc/hwpmc_mod.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_mod.c Wed Jun 6 01:51:05 2018 (r334700)
+++ head/sys/dev/hwpmc/hwpmc_mod.c Wed Jun 6 02:48:09 2018 (r334701)
@@ -3925,6 +3925,12 @@ pmc_syscall_handler(struct thread *td, void *syscall_a
pmc->pm_caps = caps;
pmc->pm_flags = pa.pm_flags;
+ /* XXX set lower bound on sampling for process counters */
+ if (PMC_IS_SAMPLING_MODE(mode))
+ pmc->pm_sc.pm_reloadcount = pa.pm_count;
+ else
+ pmc->pm_sc.pm_initial = pa.pm_count;
+
/* switch thread to CPU 'cpu' */
pmc_save_cpu_binding(&pb);
Modified: head/sys/sys/pmc.h
==============================================================================
--- head/sys/sys/pmc.h Wed Jun 6 01:51:05 2018 (r334700)
+++ head/sys/sys/pmc.h Wed Jun 6 02:48:09 2018 (r334701)
@@ -61,8 +61,8 @@
*
* The patch version is incremented for every bug fix.
*/
-#define PMC_VERSION_MAJOR 0x06
-#define PMC_VERSION_MINOR 0x02
+#define PMC_VERSION_MAJOR 0x07
+#define PMC_VERSION_MINOR 0x03
#define PMC_VERSION_PATCH 0x0000
#define PMC_VERSION (PMC_VERSION_MAJOR << 24 | \
@@ -439,6 +439,7 @@ struct pmc_op_pmcallocate {
uint32_t pm_flags; /* additional modifiers PMC_F_* */
enum pmc_mode pm_mode; /* desired mode */
pmc_id_t pm_pmcid; /* [return] process pmc id */
+ pmc_value_t pm_count; /* initial/sample count */
union pmc_md_op_pmcallocate pm_md; /* MD layer extensions */
};
Modified: head/sys/sys/pmclog.h
==============================================================================
--- head/sys/sys/pmclog.h Wed Jun 6 01:51:05 2018 (r334700)
+++ head/sys/sys/pmclog.h Wed Jun 6 02:48:09 2018 (r334701)
@@ -162,6 +162,7 @@ struct pmclog_pmcallocate {
uint32_t pl_pmcid;
uint32_t pl_event;
uint32_t pl_flags;
+ uint64_t pl_rate;
} __packed;
struct pmclog_pmcattach {
@@ -190,6 +191,8 @@ struct pmclog_proccsw {
struct pmclog_proccreate {
PMCLOG_ENTRY_HEADER
uint32_t pl_pid;
+ uint32_t pl_flags;
+ uint32_t pl_pad;
uint64_t pl_pcomm[MAXCOMLEN+1]; /* keep 8 byte aligned */
} __packed;
@@ -226,7 +229,7 @@ struct pmclog_threadcreate {
PMCLOG_ENTRY_HEADER
uint32_t pl_tid;
uint32_t pl_pid;
- uint32_t pl_pad;
+ uint32_t pl_flags;
uint64_t pl_tdname[MAXCOMLEN+1]; /* keep 8 byte aligned */
} __packed;
Modified: head/usr.sbin/pmc/Makefile
==============================================================================
--- head/usr.sbin/pmc/Makefile Wed Jun 6 01:51:05 2018 (r334700)
+++ head/usr.sbin/pmc/Makefile Wed Jun 6 02:48:09 2018 (r334701)
@@ -5,11 +5,12 @@
.include <src.opts.mk>
PROG_CXX= pmc
MAN=
-CXXFLAGS+= -O0
+CXXFLAGS+=
LIBADD= kvm pmc m ncursesw pmcstat elf
SRCS= pmc.c pmc_util.c cmd_pmc_stat.c \
- cmd_pmc_list.c cmd_pmc_filter.cc
+ cmd_pmc_list.c cmd_pmc_filter.cc \
+ cmd_pmc_summary.cc
.include <bsd.prog.mk>
Modified: head/usr.sbin/pmc/cmd_pmc.h
==============================================================================
--- head/usr.sbin/pmc/cmd_pmc.h Wed Jun 6 01:51:05 2018 (r334700)
+++ head/usr.sbin/pmc/cmd_pmc.h Wed Jun 6 02:48:09 2018 (r334701)
@@ -47,6 +47,7 @@ extern "C" {
int cmd_pmc_filter(int, char **);
int cmd_pmc_stat_system(int, char **);
int cmd_pmc_list_events(int, char **);
+ int cmd_pmc_summary(int, char **);
#if defined(__cplusplus)
};
#endif
Modified: head/usr.sbin/pmc/cmd_pmc_filter.cc
==============================================================================
--- head/usr.sbin/pmc/cmd_pmc_filter.cc Wed Jun 6 01:51:05 2018 (r334700)
+++ head/usr.sbin/pmc/cmd_pmc_filter.cc Wed Jun 6 02:48:09 2018 (r334701)
@@ -70,13 +70,12 @@ __FBSDID("$FreeBSD$");
#include <iostream>
#include <string>
-#if _LIBCPP_STD_VER >= 11
#include <unordered_map>
+
using std::unordered_map;
-#else
-#include <tr1/unordered_map>
-using std::tr1::unordered_map;
-#endif
+typedef unordered_map <int, std::string> idmap;
+typedef std::pair <int, std::string> identry;
+
#define LIST_MAX 64
static struct option longopts[] = {
{"lwps", required_argument, NULL, 't'},
@@ -158,10 +157,6 @@ struct pmcid_ent {
(PMCLOG_TYPE_ ## T << 16) | \
((L) & 0xFFFF))
-
-typedef unordered_map < int ,std::string > idmap;
-typedef std::pair < int ,std::string > identry;
-
static bool
pmc_find_name(idmap & map, uint32_t id, char *list[LIST_MAX], int count)
{
@@ -234,9 +229,9 @@ pmc_filter_handler(uint32_t *lwplist, int lwpcount, ui
copies = 0;
while (pmclog_read(ps, &ev) == 0) {
if (ev.pl_type == PMCLOG_TYPE_THR_CREATE)
- tidmap.insert(identry(ev.pl_u.pl_tc.pl_tid, ev.pl_u.pl_tc.pl_tdname));
+ tidmap[ev.pl_u.pl_tc.pl_tid] = ev.pl_u.pl_tc.pl_tdname;
if (ev.pl_type == PMCLOG_TYPE_PROC_CREATE)
- pidmap.insert(identry(ev.pl_u.pl_pc.pl_pid, ev.pl_u.pl_pc.pl_pcomm));
+ pidmap[ev.pl_u.pl_pc.pl_pid] = ev.pl_u.pl_pc.pl_pcomm;
if (ev.pl_type != PMCLOG_TYPE_CALLCHAIN) {
if (write(outfd, ev.pl_data, ev.pl_len) != (ssize_t)ev.pl_len)
errx(EX_OSERR, "ERROR: failed output write");
Modified: head/usr.sbin/pmc/cmd_pmc_stat.c
==============================================================================
--- head/usr.sbin/pmc/cmd_pmc_stat.c Wed Jun 6 01:51:05 2018 (r334700)
+++ head/usr.sbin/pmc/cmd_pmc_stat.c Wed Jun 6 02:48:09 2018 (r334701)
@@ -354,7 +354,7 @@ pmc_stat_internal(int argc, char **argv, int system_mo
STAILQ_FOREACH(ev, &pmc_args.pa_events, ev_next) {
if (pmc_allocate(ev->ev_spec, ev->ev_mode,
- ev->ev_flags, ev->ev_cpu, &ev->ev_pmcid) < 0)
+ ev->ev_flags, ev->ev_cpu, &ev->ev_pmcid, ev->ev_count) < 0)
err(EX_OSERR,
"ERROR: Cannot allocate %s-mode pmc with specification \"%s\"",
PMC_IS_SYSTEM_MODE(ev->ev_mode) ?
Added: head/usr.sbin/pmc/cmd_pmc_summary.cc
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/usr.sbin/pmc/cmd_pmc_summary.cc Wed Jun 6 02:48:09 2018 (r334701)
@@ -0,0 +1,220 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2018, Matthew Macy
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/cpuset.h>
+#include <sys/event.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/ttycom.h>
+#include <sys/user.h>
+#include <sys/wait.h>
+
+#include <assert.h>
+#include <curses.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <kvm.h>
+#include <libgen.h>
+#include <limits.h>
+#include <locale.h>
+#include <math.h>
+#include <pmc.h>
+#include <pmclog.h>
+#include <regex.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include <libpmcstat.h>
+#include "cmd_pmc.h"
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <unordered_map>
+
+using std::unordered_map;
+typedef unordered_map <int, std::string> idmap;
+typedef unordered_map <uint32_t, uint64_t> intmap;
+typedef unordered_map <std::string, intmap> strintmap;
+typedef std::pair<uint64_t, uint32_t> sampleid;
+typedef std::pair<uint64_t, std::string> samplename;
+typedef unordered_map <uint32_t, std::vector<samplename>> eventcountmap;
+
+#define P_KPROC 0x00004 /* Kernel process. */
+
+static void
+usage(void)
+{
+ errx(EX_USAGE,
+ "\t summarize log file\n"
+ "\t -k <k>, --topk <k> show topk processes for each counter\n"
+ );
+}
+
+static int
+pmc_summary_handler(int logfd, int k, bool do_full)
+{
+ struct pmclog_parse_state *ps;
+ struct pmclog_ev ev;
+ idmap pidmap, tidmap, eventnamemap;
+ strintmap tideventmap, pideventmap;
+ intmap eventmap, pmcidmap, ratemap;
+ intmap kerntidmap, kernpidmap;
+ eventcountmap countmap;
+
+ ps = static_cast<struct pmclog_parse_state*>(pmclog_open(logfd));
+ if (ps == NULL)
+ errx(EX_OSERR, "ERROR: Cannot allocate pmclog parse state: %s\n",
+ strerror(errno));
+ while (pmclog_read(ps, &ev) == 0) {
+ if (ev.pl_type == PMCLOG_TYPE_PMCALLOCATE) {
+ pmcidmap[ev.pl_u.pl_a.pl_pmcid] = ev.pl_u.pl_a.pl_event;
+ ratemap[ev.pl_u.pl_a.pl_event] = ev.pl_u.pl_a.pl_rate;
+ eventnamemap[ev.pl_u.pl_a.pl_event] = ev.pl_u.pl_a.pl_evname;
+ }
+ if (ev.pl_type == PMCLOG_TYPE_THR_CREATE) {
+ tidmap[ev.pl_u.pl_tc.pl_tid] = ev.pl_u.pl_tc.pl_tdname;
+ kerntidmap[ev.pl_u.pl_tc.pl_tid] = !!(ev.pl_u.pl_tc.pl_flags & P_KPROC);
+ if (tideventmap.find(ev.pl_u.pl_tc.pl_tdname) == tideventmap.end())
+ tideventmap[ev.pl_u.pl_tc.pl_tdname] = intmap();
+ }
+ if (ev.pl_type == PMCLOG_TYPE_PROC_CREATE) {
+ pidmap[ev.pl_u.pl_pc.pl_pid] = ev.pl_u.pl_pc.pl_pcomm;
+ kernpidmap[ev.pl_u.pl_pc.pl_pid] = !!(ev.pl_u.pl_pc.pl_flags & P_KPROC);
+ if (pideventmap.find(ev.pl_u.pl_pc.pl_pcomm) == pideventmap.end())
+ pideventmap[ev.pl_u.pl_pc.pl_pcomm] = intmap();
+ }
+ if (ev.pl_type == PMCLOG_TYPE_CALLCHAIN) {
+ auto event = pmcidmap[ev.pl_u.pl_cc.pl_pmcid];
+
+ if (event == 0)
+ continue;
+ eventmap[event]++;
+ auto tidname = tidmap.find(ev.pl_u.pl_cc.pl_tid);
+ auto pidname = pidmap.find(ev.pl_u.pl_cc.pl_pid);
+ if (tidname != tidmap.end()) {
+ auto &teventmap = tideventmap[tidname->second];
+ teventmap[event]++;
+ }
+ if (pidname != pidmap.end()) {
+ auto &peventmap = pideventmap[pidname->second];
+ peventmap[event]++;
+ }
+ }
+ }
+ for (auto &pkv : pideventmap)
+ for (auto &ekv : pkv.second) {
+ auto &samplevec = countmap[ekv.first];
+ samplevec.emplace_back(ekv.second, pkv.first);
+ }
+ for (auto &kv : countmap)
+ std::sort(kv.second.begin(), kv.second.end(), [](auto &a, auto &b) {return (a.first < b.first);});
+ if (do_full) {
+ for (auto &kv : countmap) {
+ auto &name = eventnamemap[kv.first];
+ auto rate = ratemap[kv.first];
+ std::cout << "idx: " << kv.first << " name: " << name << " rate: " << rate << std::endl;
+ while (!kv.second.empty()) {
+ auto &val = kv.second.back();
+ kv.second.pop_back();
+ std::cout << val.second << ": " << val.first << std::endl;
+ }
+ }
+ return (0);
+ }
+ for (auto &kv : countmap) {
+ auto &name = eventnamemap[kv.first];
+ auto rate = ratemap[kv.first];
+ std::cout << name << ":" << std::endl;
+ for (auto i = 0; i < k; i++) {
+ auto largest = kv.second.back();
+ kv.second.pop_back();
+ std::cout << "\t" << largest.second << ": " << largest.first*rate << std::endl;
+ }
+ }
+ return (0);
+}
+
+static struct option longopts[] = {
+ {"full", no_argument, NULL, 'f'},
+ {"topk", required_argument, NULL, 'k'},
+ {NULL, 0, NULL, 0}
+};
+
+int
+cmd_pmc_summary(int argc, char **argv)
+{
+ int option, logfd, k;
+ bool do_full;
+
+ do_full = false;
+ k = 5;
+ while ((option = getopt_long(argc, argv, "k:f", longopts, NULL)) != -1) {
+ switch (option) {
+ case 'f':
+ do_full = 1;
+ break;
+ case 'k':
+ k = atoi(optarg);
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if (argc != 1) {
+ printf("argc: %d\n", argc);
+ for (int i = 0; i < argc; i++)
+ printf("%s\n", argv[i]);
+ usage();
+ }
+ if ((logfd = open(argv[0], O_RDONLY,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0)
+ errx(EX_OSERR, "ERROR: Cannot open \"%s\" for reading: %s.", argv[0],
+ strerror(errno));
+
+ return (pmc_summary_handler(logfd, k, do_full));
+}
Modified: head/usr.sbin/pmc/pmc.c
==============================================================================
--- head/usr.sbin/pmc/pmc.c Wed Jun 6 01:51:05 2018 (r334700)
+++ head/usr.sbin/pmc/pmc.c Wed Jun 6 02:48:09 2018 (r334701)
@@ -66,6 +66,7 @@ static struct cmd_handler disp_table[] = {
{"stat-system", cmd_pmc_stat_system},
{"list-events", cmd_pmc_list_events},
{"filter", cmd_pmc_filter},
+ {"summary", cmd_pmc_summary},
{NULL, NULL}
};
Modified: head/usr.sbin/pmcstat/pmcstat.c
==============================================================================
--- head/usr.sbin/pmcstat/pmcstat.c Wed Jun 6 01:51:05 2018 (r334700)
+++ head/usr.sbin/pmcstat/pmcstat.c Wed Jun 6 02:48:09 2018 (r334701)
@@ -1129,7 +1129,8 @@ main(int argc, char **argv)
STAILQ_FOREACH(ev, &args.pa_events, ev_next) {
if (pmc_allocate(ev->ev_spec, ev->ev_mode,
- ev->ev_flags, ev->ev_cpu, &ev->ev_pmcid) < 0)
+ ev->ev_flags, ev->ev_cpu, &ev->ev_pmcid,
+ ev->ev_count) < 0)
err(EX_OSERR,
"ERROR: Cannot allocate %s-mode pmc with specification \"%s\"",
PMC_IS_SYSTEM_MODE(ev->ev_mode) ?
More information about the svn-src-head
mailing list