From owner-svn-src-all@freebsd.org Wed Jun 6 02:48:13 2018 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 99ECAFDDA19; Wed, 6 Jun 2018 02:48:13 +0000 (UTC) (envelope-from mmacy@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4807A7F743; Wed, 6 Jun 2018 02:48:13 +0000 (UTC) (envelope-from mmacy@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 2720C24FA9; Wed, 6 Jun 2018 02:48:13 +0000 (UTC) (envelope-from mmacy@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w562mDS7083151; Wed, 6 Jun 2018 02:48:13 GMT (envelope-from mmacy@FreeBSD.org) Received: (from mmacy@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w562m9tB083134; Wed, 6 Jun 2018 02:48:09 GMT (envelope-from mmacy@FreeBSD.org) Message-Id: <201806060248.w562m9tB083134@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mmacy set sender to mmacy@FreeBSD.org using -f From: Matt Macy Date: Wed, 6 Jun 2018 02:48:09 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r334701 - in head: lib/libpmc share/examples/hwpmc sys/dev/hwpmc sys/sys usr.sbin/pmc usr.sbin/pmcstat X-SVN-Group: head X-SVN-Commit-Author: mmacy X-SVN-Commit-Paths: in head: lib/libpmc share/examples/hwpmc sys/dev/hwpmc sys/sys usr.sbin/pmc usr.sbin/pmcstat X-SVN-Commit-Revision: 334701 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 06 Jun 2018 02:48:13 -0000 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 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 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 #include -#if _LIBCPP_STD_VER >= 11 #include + using std::unordered_map; -#else -#include -using std::tr1::unordered_map; -#endif +typedef unordered_map idmap; +typedef std::pair 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "cmd_pmc.h" + +#include +#include +#include +#include + +using std::unordered_map; +typedef unordered_map idmap; +typedef unordered_map intmap; +typedef unordered_map strintmap; +typedef std::pair sampleid; +typedef std::pair samplename; +typedef unordered_map > eventcountmap; + +#define P_KPROC 0x00004 /* Kernel process. */ + +static void +usage(void) +{ + errx(EX_USAGE, + "\t summarize log file\n" + "\t -k , --topk 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(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) ?