kinect/codes/Azure-Kinect-Sensor-SDK/tools/k4aviewer/perfcounter.h

137 lines
3.0 KiB
C++

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#ifndef PERFCOUNTER_H
#define PERFCOUNTER_H
// System headers
//
#include <algorithm>
#include <array>
#include <chrono>
#include <map>
#include <mutex>
#include <numeric>
#include <ratio>
// Library headers
//
#include "k4aimgui_all.h"
// Project headers
//
namespace k4aviewer
{
// Rudimentary performance counter for tracking down performance problems.
//
// Perf counters must last forever once declared (usually by being declared static).
//
class PerfCounter;
class PerfCounterManager
{
public:
static void RegisterPerfCounter(const char *name, PerfCounter *perfCounter);
static void ShowPerfWindow(bool *windowOpen);
private:
static PerfCounterManager &Instance();
std::map<std::string, PerfCounter *> m_perfCounters;
std::mutex m_mutex;
};
// A wrapper for taking a single perf measurement. Timing starts when the sample is created.
//
struct PerfSample
{
inline PerfSample(PerfCounter *counter) :
m_counter(counter),
m_currentSampleStart(std::chrono::high_resolution_clock::now())
{
}
// End the sample early
//
inline void End();
inline ~PerfSample()
{
End();
}
private:
PerfCounter *m_counter;
std::chrono::high_resolution_clock::time_point m_currentSampleStart;
};
class PerfCounter
{
public:
using SampleData = std::array<float, 100>;
PerfCounter(const char *name)
{
PerfCounterManager::RegisterPerfCounter(name, this);
}
PerfCounter(const std::string &name) : PerfCounter(name.c_str()) {}
inline float GetMax() const
{
return m_max;
}
inline float GetAverage() const
{
return static_cast<float>(std::accumulate(m_samples.begin(), m_samples.end(), 0.0) / m_samples.size());
}
inline const SampleData &GetSampleData() const
{
return m_samples;
}
inline size_t GetCurrentSampleId() const
{
return m_currentSample;
}
inline void EndSample(std::chrono::high_resolution_clock::time_point startTime)
{
const auto endTime = std::chrono::high_resolution_clock::now();
const long long durationNs = std::chrono::duration_cast<std::chrono::nanoseconds>(endTime - startTime).count();
const float durationMs = durationNs * 1.0f * std::milli::den / std::milli::num * std::nano::num /
std::nano::den;
m_max = std::max(m_max, durationMs);
m_currentSample = (m_currentSample + 1) % m_samples.size();
m_samples[m_currentSample] = durationMs;
}
inline void Reset()
{
m_max = 0;
std::fill(m_samples.begin(), m_samples.end(), 0.0f);
}
private:
float m_max = 0;
size_t m_currentSample = 0;
SampleData m_samples;
};
inline void PerfSample::End()
{
if (m_counter)
{
m_counter->EndSample(m_currentSampleStart);
m_counter = nullptr;
}
}
} // namespace k4aviewer
#endif