Browse Source
Common: Remove section measurement from profiler (#1731)
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/15/merge
13 changed files with 8 additions and 306 deletions
-
26src/citra_qt/debugger/profiler.cpp
-
1src/common/CMakeLists.txt
-
3src/common/microprofileui.h
-
82src/common/profiler.cpp
-
152src/common/profiler.h
-
27src/common/profiler_reporting.h
-
7src/core/arm/dyncom/arm_dyncom_interpreter.cpp
-
1src/core/hle/service/gsp_gpu.cpp
-
4src/core/hle/svc.cpp
-
4src/video_core/command_processor.cpp
-
3src/video_core/rasterizer.cpp
-
1src/video_core/renderer_opengl/gl_rasterizer.cpp
-
3src/video_core/shader/shader.cpp
@ -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 |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue