summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/PerformanceTracker.h
blob: 358de676b4ea5fa9f273031a17c2c6e03b867fea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// Copyright 2022 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include <atomic>
#include <deque>
#include <fstream>
#include <optional>

#include "Common/CommonTypes.h"
#include "Common/SPSCQueue.h"

class PerformanceTracker
{
public:
  PerformanceTracker(const std::optional<std::string> log_name = std::nullopt,
                     const std::optional<DT> sample_window_duration = std::nullopt);
  ~PerformanceTracker() = default;

  PerformanceTracker(const PerformanceTracker&) = delete;
  PerformanceTracker& operator=(const PerformanceTracker&) = delete;
  PerformanceTracker(PerformanceTracker&&) = delete;
  PerformanceTracker& operator=(PerformanceTracker&&) = delete;

  void Reset();

  // Calls must come from the same thread.
  // UpdateStats is expected to be called regularly to empty the SPSC queue.
  void UpdateStats();
  void ImPlotPlotLines(const char* label) const;

  // May call from any thread, but not concurrently, not that you'd want to..
  void Count();

  // May call from any thread.
  DT GetSampleWindow() const;
  double GetHzAvg() const;
  DT GetDtAvg() const;
  DT GetDtStd() const;
  DT GetLastRawDt() const;
  void InvalidateLastTime();

private:
  void LogRenderTimeToFile(DT val);

  void HandleRawDt(DT value);
  void PushFront(DT value);
  void PopBack();

  // Name of log file and file stream
  std::optional<std::string> m_log_name;
  std::ofstream m_bench_file;

  // Last time Count() was called
  TimePoint m_last_time;
  std::atomic<bool> m_is_last_time_sane = false;

  // Push'd from Count()
  //  and Pop'd from UpdateStats()
  Common::SPSCQueue<DT> m_raw_dts;
  std::atomic<DT> m_last_raw_dt = DT::zero();

  // Amount of time to sample dt's over (defaults to config)
  const std::optional<DT> m_sample_window_duration;

  // Queue + Running Total used to calculate average dt
  DT m_dt_total = DT::zero();
  std::deque<DT> m_dt_queue;

  // Average rate/time throughout the window
  std::atomic<DT> m_dt_avg = DT::zero();  // Uses Moving Average
  std::atomic<double> m_hz_avg = 0.0;     // Uses Moving Average + Euler Average
  std::atomic<DT> m_dt_std = DT::zero();
};