diff --git a/filament/src/driver/CommandStream.cpp b/filament/src/driver/CommandStream.cpp index f92cce3eb2..d15a074b33 100644 --- a/filament/src/driver/CommandStream.cpp +++ b/filament/src/driver/CommandStream.cpp @@ -62,12 +62,12 @@ CommandStream::CommandStream(Driver& driver, CircularBuffer& buffer) noexcept void CommandStream::execute(void* buffer) { SYSTRACE_CALL(); - Profiler::Counters c0; + + Profiler profiler; if (SYSTRACE_TAG) { // we want to remove all this when tracing is completely disabled - Profiler& profiler = Profiler::get(); - profiler.reset(); + profiler.resetEvents(Profiler::EV_CPU_CYCLES | Profiler::EV_L1D_RATES | Profiler::EV_BPU_RATES); profiler.start(); } @@ -79,17 +79,15 @@ void CommandStream::execute(void* buffer) { if (SYSTRACE_TAG) { // we want to remove all this when tracing is completely disabled - Profiler& profiler = Profiler::get(); - profiler.readCounters(&c0); - profiler.stop(); - SYSTRACE_VALUE32("GLThread (I)", c0.getInstructions()); - SYSTRACE_VALUE32("GLThread (C)", c0.getCpuCycles()); - SYSTRACE_VALUE32("GLThread (CPI x10)", c0.getCPI() * 10); - SYSTRACE_VALUE32("GLThread (L1D HR%)", c0.getL1DHitRate() * 100); + UTILS_UNUSED Profiler::Counters counters = profiler.readCounters(); + SYSTRACE_VALUE32("GLThread (I)", counters.getInstructions()); + SYSTRACE_VALUE32("GLThread (C)", counters.getCpuCycles()); + SYSTRACE_VALUE32("GLThread (CPI x10)", counters.getCPI() * 10); + SYSTRACE_VALUE32("GLThread (L1D HR%)", counters.getL1DHitRate() * 100); if (profiler.hasBranchRates()) { - SYSTRACE_VALUE32("GLThread (BHR%)", c0.getBranchHitRate() * 100); + SYSTRACE_VALUE32("GLThread (BHR%)", counters.getBranchHitRate() * 100); } else { - SYSTRACE_VALUE32("GLThread (BPU miss)", c0.getBranchMisses()); + SYSTRACE_VALUE32("GLThread (BPU miss)", counters.getBranchMisses()); } } } diff --git a/filament/test/filament_benchmark.cpp b/filament/test/filament_benchmark.cpp index 087199ac25..b2b9347779 100644 --- a/filament/test/filament_benchmark.cpp +++ b/filament/test/filament_benchmark.cpp @@ -42,14 +42,12 @@ void printResults(char const* name, size_t REPEAT, Profiler::Counters const& c) std::cout << "" << std::endl; } -template +template void benchmark(Profiler& p, const char* const name, T f) { - Profiler::Counters b; - Profiler::Counters c; p.start(); #pragma nounroll - for (size_t j=0 ; j<2 ; j++) { + for (size_t j = 0; j < 2; j++) { p.reset(); #pragma nounroll for (size_t i = 0; i < REPEAT; i++) { @@ -58,7 +56,7 @@ void benchmark(Profiler& p, const char* const name, T f) { } p.stop(); - p.readCounters(&c); + Profiler::Counters c = p.readCounters(); printResults(name, REPEAT, c); } @@ -103,12 +101,7 @@ int main() { Culler::result_type * __restrict__ visibles = nullptr; posix_memalign((void**)&visibles, 32, batch * sizeof(*visibles)); - Profiler::Counters c; - Profiler& p = Profiler::get(); - p.resetEvents( - Profiler::EV_CPU_CYCLES | - Profiler::EV_BPU_MISSES - ); + Profiler p(Profiler::EV_CPU_CYCLES | Profiler::EV_BPU_MISSES); benchmark(p, "Box Culling Direct", [&]() { Culler::Test::intersects(visibles, frustum, boxesCenter.data(), boxesExtent.data(), batch); diff --git a/filament/test/filament_calls.cpp b/filament/test/filament_calls.cpp index b59769d843..cba1b5c730 100644 --- a/filament/test/filament_calls.cpp +++ b/filament/test/filament_calls.cpp @@ -35,8 +35,6 @@ void printResults(char const* name, size_t REPEAT, Profiler::Counters const& c) template void benchmark(Profiler& p, const char* const name, T f) { size_t REPEAT = 128; - Profiler::Counters b; - Profiler::Counters c; p.start(); #pragma nounroll @@ -49,7 +47,7 @@ void benchmark(Profiler& p, const char* const name, T f) { } p.stop(); - p.readCounters(&c); + Profiler::Counters c = p.readCounters(); printResults(name, REPEAT, c); } @@ -57,8 +55,6 @@ void benchmark(Profiler& p, const char* const name, T f) { template void benchmark_nounroll(Profiler& p, const char* const name, T f) { size_t REPEAT = 128; - Profiler::Counters b; - Profiler::Counters c; p.start(); #pragma nounroll @@ -71,7 +67,7 @@ void benchmark_nounroll(Profiler& p, const char* const name, T f) { } p.stop(); - p.readCounters(&c); + Profiler::Counters c = p.readCounters(); printResults(name, REPEAT, c); } @@ -91,12 +87,7 @@ int main() { filament::details::EnginePerformanceTest* ei = engine; filament::details::EnginePerformanceTest::PFN destroyUniverse = engine->getDestroyUniverseApi(); - Profiler::Counters c; - Profiler& p = Profiler::get(); - p.resetEvents( - Profiler::EV_CPU_CYCLES | - Profiler::EV_BPU_MISSES - ); + Profiler p(Profiler::EV_CPU_CYCLES | Profiler::EV_BPU_MISSES); benchmark(p, "Local function call", [engine]() { foo(engine); diff --git a/libs/utils/include/utils/Profiler.h b/libs/utils/include/utils/Profiler.h index 80d0bdb5e4..218e21c26e 100644 --- a/libs/utils/include/utils/Profiler.h +++ b/libs/utils/include/utils/Profiler.h @@ -29,6 +29,8 @@ # include #endif +#include + namespace utils { class Profiler { @@ -62,8 +64,9 @@ public: EV_BPU_RATES = EV_BPU_REFS | EV_BPU_MISSES, }; - static Profiler& get() noexcept; - + Profiler() noexcept; // must call resetEvents() + explicit Profiler(uint32_t eventMask) noexcept; + ~Profiler() noexcept; Profiler(const Profiler& rhs) = delete; Profiler(Profiler&& rhs) = delete; @@ -71,7 +74,6 @@ public: Profiler& operator=(Profiler&& rhs) = delete; // selects which events are enabled. - // By Default: EV_CPU_CYCLES | EV_L1D_RATES | EV_BPU_RATES uint32_t resetEvents(uint32_t eventMask) noexcept; uint32_t getEnabledEvents() const noexcept { return mEnabledEvents; } @@ -93,7 +95,7 @@ public: lhs.nr -= rhs.nr; lhs.time_enabled -= rhs.time_enabled; lhs.time_running -= rhs.time_running; - for (size_t i=0 ; i 0) { - outCounters->nr = counters.nr; - outCounters->time_enabled = counters.time_enabled; - outCounters->time_running = counters.time_running; - for (size_t i=0 ; i= 0) { - outCounters->counters[i] = counters.counters[mIds[i]]; + outCounters.counters[i] = counters.counters[mIds[i]]; } } } + return outCounters; } #else // !__linux__ @@ -202,7 +205,7 @@ public: void reset() noexcept { } void start() noexcept { } void stop() noexcept { } - void readCounters(Counters* counters) noexcept { } + Counters readCounters() noexcept { return {}; } #endif // __linux__ @@ -215,10 +218,7 @@ public: } private: - Profiler() noexcept; - ~Profiler() noexcept; - - __attribute__((unused)) uint8_t mIds[EVENT_COUNT]; + UTILS_UNUSED uint8_t mIds[EVENT_COUNT]; int mCountersFd[EVENT_COUNT]; uint32_t mEnabledEvents = 0; }; diff --git a/libs/utils/src/Profiler.cpp b/libs/utils/src/Profiler.cpp index 53259b7abe..69ecf0e002 100644 --- a/libs/utils/src/Profiler.cpp +++ b/libs/utils/src/Profiler.cpp @@ -18,11 +18,12 @@ #include #include + #if !defined(WIN32) -#include +# include #else -#include -#define close _close +# include +# define close _close #endif #include @@ -43,23 +44,21 @@ }; #endif -static int perf_event_open(struct perf_event_attr* hw_event, pid_t pid, +static int perf_event_open(perf_event_attr* hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags) { - return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); + return (int)syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); } #endif // __linux__ namespace utils { -Profiler& Profiler::get() noexcept { - static Profiler sProfiler; - return sProfiler; -} - Profiler::Profiler() noexcept { std::uninitialized_fill(std::begin(mCountersFd), std::end(mCountersFd), -1); - Profiler::resetEvents(EV_CPU_CYCLES | EV_L1D_RATES | EV_BPU_RATES); +} + +Profiler::Profiler(uint32_t eventMask) noexcept : Profiler() { + Profiler::resetEvents(eventMask); } Profiler::~Profiler() noexcept { @@ -84,10 +83,9 @@ uint32_t Profiler::resetEvents(uint32_t eventMask) noexcept { #if defined(__linux__) - struct perf_event_attr pe; - memset(&pe, 0, sizeof(struct perf_event_attr)); + perf_event_attr pe{}; pe.type = PERF_TYPE_HARDWARE; - pe.size = sizeof(struct perf_event_attr); + pe.size = sizeof(perf_event_attr); pe.config = PERF_COUNT_HW_INSTRUCTIONS; pe.disabled = 1; pe.exclude_kernel = 1;