mirror of https://github.com/yuzu-mirror/yuzu
Common: Remove section measurement from profiler (#1731)
This has been entirely superseded by MicroProfile. The rest of the code can go when a simpler frametime/FPS meter is added to the GUI.pull/8/head
parent
90501f20e6
commit
e3a8292495
@ -1,152 +0,0 @@
|
|||||||
// Copyright 2015 Citra Emulator Project
|
|
||||||
// Licensed under GPLv2 or any later version
|
|
||||||
// Refer to the license.txt file included.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
#include <chrono>
|
|
||||||
|
|
||||||
#include "common/assert.h"
|
|
||||||
#include "common/thread.h"
|
|
||||||
|
|
||||||
namespace Common {
|
|
||||||
namespace Profiling {
|
|
||||||
|
|
||||||
// If this is defined to 0, it turns all Timers into no-ops.
|
|
||||||
#ifndef ENABLE_PROFILING
|
|
||||||
#define ENABLE_PROFILING 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER <= 1800 // MSVC 2013
|
|
||||||
// MSVC up to 2013 doesn't use QueryPerformanceCounter for high_resolution_clock, so it has bad
|
|
||||||
// precision. We manually implement a clock based on QPC to get good results.
|
|
||||||
|
|
||||||
struct QPCClock {
|
|
||||||
using duration = std::chrono::microseconds;
|
|
||||||
using time_point = std::chrono::time_point<QPCClock>;
|
|
||||||
using rep = duration::rep;
|
|
||||||
using period = duration::period;
|
|
||||||
static const bool is_steady = false;
|
|
||||||
|
|
||||||
static time_point now();
|
|
||||||
};
|
|
||||||
|
|
||||||
using Clock = QPCClock;
|
|
||||||
#else
|
|
||||||
using Clock = std::chrono::high_resolution_clock;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using Duration = Clock::duration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a timing category that measured time can be accounted towards. Should be declared as a
|
|
||||||
* global variable and passed to Timers.
|
|
||||||
*/
|
|
||||||
class TimingCategory final {
|
|
||||||
public:
|
|
||||||
TimingCategory(const char* name, TimingCategory* parent = nullptr);
|
|
||||||
|
|
||||||
unsigned int GetCategoryId() const {
|
|
||||||
return category_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Adds some time to this category. Can safely be called from multiple threads at the same time.
|
|
||||||
void AddTime(Duration amount) {
|
|
||||||
std::atomic_fetch_add_explicit(
|
|
||||||
&accumulated_duration, amount.count(),
|
|
||||||
std::memory_order_relaxed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Atomically retrieves the accumulated measured time for this category and resets the counter
|
|
||||||
* to zero. Can be safely called concurrently with AddTime.
|
|
||||||
*/
|
|
||||||
Duration GetAccumulatedTime() {
|
|
||||||
return Duration(std::atomic_exchange_explicit(
|
|
||||||
&accumulated_duration, (Duration::rep)0,
|
|
||||||
std::memory_order_relaxed));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
unsigned int category_id;
|
|
||||||
std::atomic<Duration::rep> accumulated_duration;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Measures time elapsed between a call to Start and a call to Stop and attributes it to the given
|
|
||||||
* TimingCategory. Start/Stop can be called multiple times on the same timer, but each call must be
|
|
||||||
* appropriately paired.
|
|
||||||
*
|
|
||||||
* When a Timer is started, it automatically pauses a previously running timer on the same thread,
|
|
||||||
* which is resumed when it is stopped. As such, no special action needs to be taken to avoid
|
|
||||||
* double-accounting of time on two categories.
|
|
||||||
*/
|
|
||||||
class Timer {
|
|
||||||
public:
|
|
||||||
Timer(TimingCategory& category) : category(category) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void Start() {
|
|
||||||
#if ENABLE_PROFILING
|
|
||||||
ASSERT(!running);
|
|
||||||
previous_timer = current_timer;
|
|
||||||
current_timer = this;
|
|
||||||
if (previous_timer != nullptr)
|
|
||||||
previous_timer->StopTiming();
|
|
||||||
|
|
||||||
StartTiming();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void Stop() {
|
|
||||||
#if ENABLE_PROFILING
|
|
||||||
ASSERT(running);
|
|
||||||
StopTiming();
|
|
||||||
|
|
||||||
if (previous_timer != nullptr)
|
|
||||||
previous_timer->StartTiming();
|
|
||||||
current_timer = previous_timer;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
#if ENABLE_PROFILING
|
|
||||||
void StartTiming() {
|
|
||||||
start = Clock::now();
|
|
||||||
running = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StopTiming() {
|
|
||||||
auto duration = Clock::now() - start;
|
|
||||||
running = false;
|
|
||||||
category.AddTime(std::chrono::duration_cast<Duration>(duration));
|
|
||||||
}
|
|
||||||
|
|
||||||
Clock::time_point start;
|
|
||||||
bool running = false;
|
|
||||||
|
|
||||||
Timer* previous_timer;
|
|
||||||
static thread_local Timer* current_timer;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
TimingCategory& category;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Timer that automatically starts timing when created and stops at the end of the scope. Should
|
|
||||||
* be used in the majority of cases.
|
|
||||||
*/
|
|
||||||
class ScopeTimer : public Timer {
|
|
||||||
public:
|
|
||||||
ScopeTimer(TimingCategory& category) : Timer(category) {
|
|
||||||
Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
~ScopeTimer() {
|
|
||||||
Stop();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Profiling
|
|
||||||
} // namespace Common
|
|
Loading…
Reference in New Issue