From 0112d49f62ccf543be82649462888f08c485c448 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Tue, 7 May 2019 17:18:39 -0700 Subject: [PATCH] ircd::prof: Add gadget for instruction profiling of a scope. --- include/ircd/prof.h | 18 +++++++++++++ ircd/prof.cc | 64 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/include/ircd/prof.h b/include/ircd/prof.h index 8695c93c4..56f99596e 100644 --- a/include/ircd/prof.h +++ b/include/ircd/prof.h @@ -20,6 +20,7 @@ namespace ircd::prof struct system; struct resource; struct syscall_timer; + struct instructions; enum dpl :uint8_t; using group = std::vector>; IRCD_OVERLOAD(sample) @@ -94,6 +95,23 @@ struct ircd::prof::vg::disable ~disable() noexcept; }; +/// Gadget for hardware profiling of instructions for a scope. +/// +struct ircd::prof::instructions +{ + prof::group group; + uint64_t val {0}; + + public: + const uint64_t &at() const; + const uint64_t &sample(); + + instructions() noexcept; + instructions(instructions &&) = delete; + instructions(const instructions &) = delete; + ~instructions() noexcept; +}; + /// This suite of devices is intended to figure out when a system call is /// really slow or "blocking." The original use-case is for io_submit() in /// fs::aio. diff --git a/ircd/prof.cc b/ircd/prof.cc index ec9cb42bf..d99b49c57 100644 --- a/ircd/prof.cc +++ b/ircd/prof.cc @@ -282,6 +282,70 @@ ircd::prof::vg::enabled() return _enabled; } +// +// instructions +// + +ircd::prof::instructions::instructions() +noexcept +{ + if(!create(this->group, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS, true, false)) + throw error + { + "Cannot sample instruction counter." + }; + + reset(this->group); + start(this->group); +} + +ircd::prof::instructions::~instructions() +noexcept +{ +} + +const uint64_t & +ircd::prof::instructions::sample() +{ + stop(this->group); + + auto &leader + { + prof::leader(group) + }; + + thread_local char buf[1024]; + const const_buffer read + { + buf, size_t(syscall(::read, int(leader.fd), buf, sizeof(buf))) + }; + + for_each(read, [this] + (const type &type, const uint64_t &val) + { + if(type.type_id == PERF_TYPE_HARDWARE) + if(type.counter == PERF_COUNT_HW_INSTRUCTIONS) + if(type.dpl == dpl::USER) + this->val += val; + }); + + const auto &ret + { + at() + }; + + start(this->group); + + return ret; +} + +const uint64_t & +ircd::prof::instructions::at() +const +{ + return val; +} + // // syscall_timer //