mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-09-05 09:05:54 +00:00
DolphinAnalytics: Extract timestamp functions
Moves functions that generate starting timestamps for performance sampling to PerformanceSampleAggregator.
This commit is contained in:
parent
d78e6fe165
commit
d9b0fd2805
4 changed files with 56 additions and 21 deletions
|
@ -27,7 +27,6 @@
|
||||||
#include "Common/Crypto/SHA1.h"
|
#include "Common/Crypto/SHA1.h"
|
||||||
#include "Common/EnumUtils.h"
|
#include "Common/EnumUtils.h"
|
||||||
#include "Common/Random.h"
|
#include "Common/Random.h"
|
||||||
#include "Common/Timer.h"
|
|
||||||
#include "Common/Version.h"
|
#include "Common/Version.h"
|
||||||
|
|
||||||
#include "Core/Config/MainSettings.h"
|
#include "Core/Config/MainSettings.h"
|
||||||
|
@ -35,7 +34,6 @@
|
||||||
#include "Core/HW/GCPad.h"
|
#include "Core/HW/GCPad.h"
|
||||||
#include "Core/Movie.h"
|
#include "Core/Movie.h"
|
||||||
#include "Core/NetPlayProto.h"
|
#include "Core/NetPlayProto.h"
|
||||||
#include "Core/PerformanceSampleAggregator.h"
|
|
||||||
|
|
||||||
#include "Core/System.h"
|
#include "Core/System.h"
|
||||||
#include "InputCommon/GCAdapter.h"
|
#include "InputCommon/GCAdapter.h"
|
||||||
|
@ -321,6 +319,7 @@ void DolphinAnalytics::ReportPerformanceInfo(PerformanceSample&& sample)
|
||||||
// Clear up and stop sampling until next time ShouldStartPerformanceSampling() says so.
|
// Clear up and stop sampling until next time ShouldStartPerformanceSampling() says so.
|
||||||
m_performance_samples.clear();
|
m_performance_samples.clear();
|
||||||
m_sampling_performance_info = false;
|
m_sampling_performance_info = false;
|
||||||
|
m_sampling_next_start_us = m_sample_aggregator.GetRepeatSamplingStartTimestamp().count();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,22 +328,13 @@ void DolphinAnalytics::InitializePerformanceSampling()
|
||||||
m_performance_samples.clear();
|
m_performance_samples.clear();
|
||||||
m_sampling_performance_info = false;
|
m_sampling_performance_info = false;
|
||||||
|
|
||||||
const u64 wait_us =
|
m_sampling_next_start_us = m_sample_aggregator.GetInitialSamplingStartTimestamp().count();
|
||||||
PERFORMANCE_SAMPLING_INITIAL_WAIT_TIME_SECS * 1000000 +
|
|
||||||
Common::Random::GenerateValue<u64>() % (PERFORMANCE_SAMPLING_WAIT_TIME_JITTER_SECS * 1000000);
|
|
||||||
m_sampling_next_start_us = Common::Timer::NowUs() + wait_us;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DolphinAnalytics::ShouldStartPerformanceSampling()
|
bool DolphinAnalytics::ShouldStartPerformanceSampling()
|
||||||
{
|
{
|
||||||
if (Common::Timer::NowUs() < m_sampling_next_start_us)
|
return static_cast<u64>(m_sample_aggregator.GetCurrentMicroseconds().count()) >=
|
||||||
return false;
|
m_sampling_next_start_us;
|
||||||
|
|
||||||
const u64 wait_us =
|
|
||||||
PERFORMANCE_SAMPLING_INTERVAL_SECS * 1000000 +
|
|
||||||
Common::Random::GenerateValue<u64>() % (PERFORMANCE_SAMPLING_WAIT_TIME_JITTER_SECS * 1000000);
|
|
||||||
m_sampling_next_start_us = Common::Timer::NowUs() + wait_us;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DolphinAnalytics::MakeBaseBuilder()
|
void DolphinAnalytics::MakeBaseBuilder()
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
|
||||||
#include "Core/PerformanceSample.h"
|
#include "Core/PerformanceSample.h"
|
||||||
|
#include "Core/PerformanceSampleAggregator.h"
|
||||||
|
|
||||||
#if defined(ANDROID)
|
#if defined(ANDROID)
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
@ -138,6 +139,10 @@ public:
|
||||||
|
|
||||||
// Reports performance information. This method performs its own throttling / aggregation --
|
// Reports performance information. This method performs its own throttling / aggregation --
|
||||||
// calling it does not guarantee when a report will actually be sent.
|
// calling it does not guarantee when a report will actually be sent.
|
||||||
|
// Performance reports are generated using data from 100 consecutive frames.
|
||||||
|
// Report starting times are randomized to obtain a wider range of sample data.
|
||||||
|
// The first report begins 5-8 minutes after a game is launched.
|
||||||
|
// Successive reports begin 30-33 minutes after the previous report finishes.
|
||||||
//
|
//
|
||||||
// This method is NOT thread-safe.
|
// This method is NOT thread-safe.
|
||||||
void ReportPerformanceInfo(PerformanceSample&& sample);
|
void ReportPerformanceInfo(PerformanceSample&& sample);
|
||||||
|
@ -165,21 +170,16 @@ private:
|
||||||
// values created by MakeUniqueId.
|
// values created by MakeUniqueId.
|
||||||
std::string m_unique_id;
|
std::string m_unique_id;
|
||||||
|
|
||||||
// Performance sampling configuration constants.
|
|
||||||
//
|
|
||||||
// 5min after startup + rand(0, 3min) jitter time, collect performance for 100 frames in a row.
|
|
||||||
// Repeat collection after 30min + rand(0, 3min).
|
|
||||||
static constexpr int NUM_PERFORMANCE_SAMPLES_PER_REPORT = 100;
|
static constexpr int NUM_PERFORMANCE_SAMPLES_PER_REPORT = 100;
|
||||||
static constexpr int PERFORMANCE_SAMPLING_INITIAL_WAIT_TIME_SECS = 300;
|
|
||||||
static constexpr int PERFORMANCE_SAMPLING_WAIT_TIME_JITTER_SECS = 180;
|
|
||||||
static constexpr int PERFORMANCE_SAMPLING_INTERVAL_SECS = 1800;
|
|
||||||
|
|
||||||
// Performance sampling state & internal helpers.
|
// Performance sampling state & internal helpers.
|
||||||
void InitializePerformanceSampling(); // Called on game start / title switch.
|
void InitializePerformanceSampling(); // Called on game start / title switch.
|
||||||
bool ShouldStartPerformanceSampling();
|
bool ShouldStartPerformanceSampling();
|
||||||
|
|
||||||
u64 m_sampling_next_start_us; // Next timestamp (in us) at which to trigger sampling.
|
u64 m_sampling_next_start_us; // Next timestamp (in us) at which to trigger sampling.
|
||||||
bool m_sampling_performance_info = false; // Whether we are currently collecting samples.
|
bool m_sampling_performance_info = false; // Whether we are currently collecting samples.
|
||||||
std::vector<PerformanceSample> m_performance_samples;
|
std::vector<PerformanceSample> m_performance_samples;
|
||||||
|
PerformanceSampleAggregator m_sample_aggregator;
|
||||||
|
|
||||||
// What quirks have already been reported about the current game.
|
// What quirks have already been reported about the current game.
|
||||||
std::array<bool, static_cast<size_t>(GameQuirk::Count)> m_reported_quirks;
|
std::array<bool, static_cast<size_t>(GameQuirk::Count)> m_reported_quirks;
|
||||||
|
|
|
@ -3,3 +3,42 @@
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include "Core/PerformanceSampleAggregator.h"
|
#include "Core/PerformanceSampleAggregator.h"
|
||||||
|
|
||||||
|
#include "Common/Random.h"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
std::chrono::microseconds GetSamplingStartTimeJitter()
|
||||||
|
{
|
||||||
|
constexpr long long max_delay = std::chrono::microseconds(std::chrono::minutes(3)).count();
|
||||||
|
return std::chrono::microseconds(Common::Random::GenerateValue<u64>() % max_delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::chrono::microseconds
|
||||||
|
GetSamplingStartTimestampUsingBaseDelay(const std::chrono::microseconds base_delay)
|
||||||
|
{
|
||||||
|
const std::chrono::microseconds now = PerformanceSampleAggregator::GetCurrentMicroseconds();
|
||||||
|
const std::chrono::microseconds jitter = GetSamplingStartTimeJitter();
|
||||||
|
const std::chrono::microseconds sampling_start_timestamp = now + base_delay + jitter;
|
||||||
|
return sampling_start_timestamp;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
std::chrono::microseconds PerformanceSampleAggregator::GetInitialSamplingStartTimestamp()
|
||||||
|
{
|
||||||
|
constexpr std::chrono::microseconds base_initial_delay = std::chrono::minutes(5);
|
||||||
|
return GetSamplingStartTimestampUsingBaseDelay(base_initial_delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::chrono::microseconds PerformanceSampleAggregator::GetRepeatSamplingStartTimestamp()
|
||||||
|
{
|
||||||
|
constexpr std::chrono::microseconds base_repeat_delay = std::chrono::minutes(30);
|
||||||
|
return GetSamplingStartTimestampUsingBaseDelay(base_repeat_delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::chrono::microseconds PerformanceSampleAggregator::GetCurrentMicroseconds()
|
||||||
|
{
|
||||||
|
const std::chrono::high_resolution_clock::duration time_since_epoch =
|
||||||
|
std::chrono::high_resolution_clock::now().time_since_epoch();
|
||||||
|
return std::chrono::duration_cast<std::chrono::microseconds>(time_since_epoch);
|
||||||
|
}
|
||||||
|
|
|
@ -4,8 +4,14 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
class PerformanceSampleAggregator
|
class PerformanceSampleAggregator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PerformanceSampleAggregator() = default;
|
PerformanceSampleAggregator() = default;
|
||||||
|
|
||||||
|
static std::chrono::microseconds GetInitialSamplingStartTimestamp();
|
||||||
|
static std::chrono::microseconds GetRepeatSamplingStartTimestamp();
|
||||||
|
static std::chrono::microseconds GetCurrentMicroseconds();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue