refactor: consolidate timing utilities into header-only Timer.h

This commit is contained in:
MatthewBeshay 2026-04-03 17:28:06 +11:00
parent 98e23cfd4d
commit 5bbb045e86
19 changed files with 214 additions and 203 deletions

View file

@ -81,7 +81,7 @@
#include "app/common/src/UI/All Platforms/ArchiveFile.h" #include "app/common/src/UI/All Platforms/ArchiveFile.h"
#include "app/common/src/UI/Scenes/In-Game Menu Screens/UIScene_PauseMenu.h" #include "app/common/src/UI/Scenes/In-Game Menu Screens/UIScene_PauseMenu.h"
#include "Minecraft_Macros.h" #include "Minecraft_Macros.h"
#include "console_helpers/PlatformTime.h" #include "console_helpers/Timer.h"
#include "console_helpers/StringHelpers.h" #include "console_helpers/StringHelpers.h"
#include "console_helpers/compression.h" #include "console_helpers/compression.h"
#include "minecraft/client/User.h" #include "minecraft/client/User.h"
@ -203,7 +203,7 @@ CMinecraftApp::CMinecraftApp() {
m_iTotalDLC = 0; m_iTotalDLC = 0;
m_iTotalDLCInstalled = 0; m_iTotalDLCInstalled = 0;
mfTrialPausedTime = 0.0f; mfTrialPausedTime = 0.0f;
m_uiAutosaveTimer = 0; m_uiAutosaveTimer = {};
memset(m_pszUniqueMapName, 0, 14); memset(m_pszUniqueMapName, 0, 14);
m_bNewDLCAvailable = false; m_bNewDLCAvailable = false;
@ -4383,15 +4383,11 @@ void CMinecraftApp::HandleDLC(DLCPack* pack) {
// Desc: Initializes the timer variables // Desc: Initializes the timer variables
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
void CMinecraftApp::InitTime() { void CMinecraftApp::InitTime() {
// Get the frequency of the timer
auto freq = PlatformTime::QueryPerformanceFrequency();
m_Time.fSecsPerTick = 1.0f / static_cast<float>(freq);
// Save the start time // Save the start time
m_Time.qwTime = PlatformTime::QueryPerformanceCounter(); m_Time.qwTime = time_util::clock::now();
// Zero out the elapsed and total time // Zero out the elapsed and total time
m_Time.qwAppTime = 0; m_Time.qwAppTime = {};
m_Time.fAppTime = 0.0f; m_Time.fAppTime = 0.0f;
m_Time.fElapsedTime = 0.0f; m_Time.fElapsedTime = 0.0f;
} }
@ -4401,15 +4397,14 @@ void CMinecraftApp::InitTime() {
// Desc: Updates the elapsed time since our last frame. // Desc: Updates the elapsed time since our last frame.
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
void CMinecraftApp::UpdateTime() { void CMinecraftApp::UpdateTime() {
auto qwNewTime = PlatformTime::QueryPerformanceCounter(); auto qwNewTime = time_util::clock::now();
auto qwDeltaTime = qwNewTime - m_Time.qwTime; auto qwDeltaTime = qwNewTime - m_Time.qwTime;
m_Time.qwAppTime += qwDeltaTime; m_Time.qwAppTime += qwDeltaTime;
m_Time.qwTime = qwNewTime; m_Time.qwTime = qwNewTime;
m_Time.fElapsedTime = m_Time.fSecsPerTick * static_cast<float>(qwDeltaTime); m_Time.fElapsedTime = std::chrono::duration<float>(qwDeltaTime).count();
m_Time.fAppTime = m_Time.fAppTime = std::chrono::duration<float>(m_Time.qwAppTime).count();
m_Time.fSecsPerTick * static_cast<float>(m_Time.qwAppTime);
} }
bool CMinecraftApp::isXuidNotch(PlayerUID xuid) { bool CMinecraftApp::isXuidNotch(PlayerUID xuid) {
@ -7175,18 +7170,18 @@ int CMinecraftApp::GetDLCInfoTexturesOffersCount() {
// AUTOSAVE // AUTOSAVE
void CMinecraftApp::SetAutosaveTimerTime(void) { void CMinecraftApp::SetAutosaveTimerTime(void) {
int settingValue = GetGameSettings(ProfileManager.GetPrimaryPad(), eGameSetting_Autosave);
m_uiAutosaveTimer = m_uiAutosaveTimer =
PlatformTime::GetTickCount() + time_util::clock::now() +
GetGameSettings(ProfileManager.GetPrimaryPad(), eGameSetting_Autosave) * std::chrono::minutes(settingValue * 15);
1000 * 60 * 15; } // value x 15 to get mins
} // value x 15 to get mins, x60 for secs
bool CMinecraftApp::AutosaveDue(void) { bool CMinecraftApp::AutosaveDue(void) {
return (PlatformTime::GetTickCount() > m_uiAutosaveTimer); return (time_util::clock::now() > m_uiAutosaveTimer);
} }
unsigned int CMinecraftApp::SecondsToAutosave() { int64_t CMinecraftApp::SecondsToAutosave() {
return (m_uiAutosaveTimer - PlatformTime::GetTickCount()) / 1000; return std::chrono::duration_cast<std::chrono::seconds>(m_uiAutosaveTimer - time_util::clock::now()).count();
} }
void CMinecraftApp::SetTrialTimerStart(void) { void CMinecraftApp::SetTrialTimerStart(void) {

View file

@ -3,6 +3,7 @@
#include <cstdint> #include <cstdint>
#include <mutex> #include <mutex>
#include "console_helpers/Timer.h"
#include "platform/sdl2/Profile.h" #include "platform/sdl2/Profile.h"
#include "platform/sdl2/Storage.h" #include "platform/sdl2/Storage.h"
@ -610,12 +611,11 @@ private:
// Trial timer // Trial timer
float m_fTrialTimerStart, mfTrialPausedTime; float m_fTrialTimerStart, mfTrialPausedTime;
typedef struct TimeInfo { typedef struct TimeInfo {
std::int64_t qwTime; time_util::time_point qwTime;
std::int64_t qwAppTime; time_util::clock::duration qwAppTime{};
float fAppTime; float fAppTime;
float fElapsedTime; float fElapsedTime;
float fSecsPerTick;
} TIMEINFO; } TIMEINFO;
TimeInfo m_Time; TimeInfo m_Time;
@ -749,10 +749,10 @@ public:
public: public:
void SetAutosaveTimerTime(void); void SetAutosaveTimerTime(void);
bool AutosaveDue(void); bool AutosaveDue(void);
unsigned int SecondsToAutosave(); int64_t SecondsToAutosave();
private: private:
unsigned int m_uiAutosaveTimer; time_util::time_point m_uiAutosaveTimer;
unsigned int m_uiOpacityCountDown[XUSER_MAX_COUNT]; unsigned int m_uiOpacityCountDown[XUSER_MAX_COUNT];
// DLC // DLC

View file

@ -25,7 +25,7 @@
#include "app/linux/Linux_App.h" #include "app/linux/Linux_App.h"
#include "app/linux/Linux_UIController.h" #include "app/linux/Linux_UIController.h"
#include "TutorialMessage.h" #include "TutorialMessage.h"
#include "console_helpers/PlatformTime.h" #include "console_helpers/Timer.h"
#include "console_helpers/StringHelpers.h" #include "console_helpers/StringHelpers.h"
#include "java/Class.h" #include "java/Class.h"
#include "minecraft/client/Minecraft.h" #include "minecraft/client/Minecraft.h"
@ -397,14 +397,14 @@ Tutorial::Tutorial(int iPad, bool isFullTutorial /*= false*/) : m_iPad(iPad) {
m_UIScene = nullptr; m_UIScene = nullptr;
m_allowShow = true; m_allowShow = true;
m_bHasTickedOnce = false; m_bHasTickedOnce = false;
m_firstTickTime = 0; m_firstTickTime = {};
// 4jcraft added, not initialized // 4jcraft added, not initialized
m_bSceneIsSplitscreen = false; m_bSceneIsSplitscreen = false;
m_lastMessage = nullptr; m_lastMessage = nullptr;
lastMessageTime = 0; lastMessageTime = {};
m_iTaskReminders = 0; m_iTaskReminders = 0;
m_lastMessageState = e_Tutorial_State_Gameplay; m_lastMessageState = e_Tutorial_State_Gameplay;
@ -2079,10 +2079,10 @@ void Tutorial::tick() {
// Don't do anything for the first 2 seconds so that the loading screen is // Don't do anything for the first 2 seconds so that the loading screen is
// gone // gone
if (!m_bHasTickedOnce) { if (!m_bHasTickedOnce) {
int time = PlatformTime::GetTickCount(); auto now = time_util::clock::now();
if (m_firstTickTime == 0) { if (m_firstTickTime == time_util::time_point{}) {
m_firstTickTime = time; m_firstTickTime = now;
} else if (time - m_firstTickTime > 1500) { } else if (now - m_firstTickTime > std::chrono::milliseconds(1500)) {
m_bHasTickedOnce = true; m_bHasTickedOnce = true;
} }
} }
@ -2132,8 +2132,8 @@ void Tutorial::tick() {
if (!m_allowShow) { if (!m_allowShow) {
if (currentTask[m_CurrentState] != nullptr && if (currentTask[m_CurrentState] != nullptr &&
(!currentTask[m_CurrentState]->AllowFade() || (!currentTask[m_CurrentState]->AllowFade() ||
(lastMessageTime + m_iTutorialDisplayMessageTime) > (lastMessageTime + std::chrono::milliseconds(m_iTutorialDisplayMessageTime)) >
PlatformTime::GetTickCount())) { time_util::clock::now())) {
uiTempDisabled = true; uiTempDisabled = true;
} }
ui.SetTutorialVisible(m_iPad, false); ui.SetTutorialVisible(m_iPad, false);
@ -2153,8 +2153,8 @@ void Tutorial::tick() {
if (ui.IsPauseMenuDisplayed(m_iPad)) { if (ui.IsPauseMenuDisplayed(m_iPad)) {
if (currentTask[m_CurrentState] != nullptr && if (currentTask[m_CurrentState] != nullptr &&
(!currentTask[m_CurrentState]->AllowFade() || (!currentTask[m_CurrentState]->AllowFade() ||
(lastMessageTime + m_iTutorialDisplayMessageTime) > (lastMessageTime + std::chrono::milliseconds(m_iTutorialDisplayMessageTime)) >
PlatformTime::GetTickCount())) { time_util::clock::now())) {
uiTempDisabled = true; uiTempDisabled = true;
} }
ui.SetTutorialVisible(m_iPad, false); ui.SetTutorialVisible(m_iPad, false);
@ -2162,7 +2162,7 @@ void Tutorial::tick() {
} }
if (uiTempDisabled) { if (uiTempDisabled) {
ui.SetTutorialVisible(m_iPad, true); ui.SetTutorialVisible(m_iPad, true);
lastMessageTime = PlatformTime::GetTickCount(); lastMessageTime = time_util::clock::now();
uiTempDisabled = false; uiTempDisabled = false;
} }
@ -2233,8 +2233,8 @@ void Tutorial::tick() {
isCurrentTask = false; isCurrentTask = false;
if ((!task->ShowMinimumTime() || if ((!task->ShowMinimumTime() ||
(task->hasBeenActivated() && (task->hasBeenActivated() &&
(lastMessageTime + m_iTutorialMinimumDisplayMessageTime) < (lastMessageTime + std::chrono::milliseconds(m_iTutorialMinimumDisplayMessageTime)) <
PlatformTime::GetTickCount())) && time_util::clock::now())) &&
task->isCompleted()) { task->isCompleted()) {
eTutorial_CompletionAction compAction = eTutorial_CompletionAction compAction =
task->getCompletionAction(); task->getCompletionAction();
@ -2324,8 +2324,8 @@ void Tutorial::tick() {
} }
if (task != nullptr && task->ShowMinimumTime() && if (task != nullptr && task->ShowMinimumTime() &&
task->hasBeenActivated() && task->hasBeenActivated() &&
(lastMessageTime + m_iTutorialMinimumDisplayMessageTime) < (lastMessageTime + std::chrono::milliseconds(m_iTutorialMinimumDisplayMessageTime)) <
PlatformTime::GetTickCount()) { time_util::clock::now()) {
task->setShownForMinimumTime(); task->setShownForMinimumTime();
if (!m_hintDisplayed) { if (!m_hintDisplayed) {
@ -2393,15 +2393,15 @@ void Tutorial::tick() {
} }
} }
if (m_hintDisplayed && (lastMessageTime + m_iTutorialDisplayMessageTime) < if (m_hintDisplayed && (lastMessageTime + std::chrono::milliseconds(m_iTutorialDisplayMessageTime)) <
PlatformTime::GetTickCount()) { time_util::clock::now()) {
m_hintDisplayed = false; m_hintDisplayed = false;
} }
if (currentFailedConstraint[m_CurrentState] == nullptr && if (currentFailedConstraint[m_CurrentState] == nullptr &&
currentTask[m_CurrentState] != nullptr && (m_iTaskReminders != 0) && currentTask[m_CurrentState] != nullptr && (m_iTaskReminders != 0) &&
(lastMessageTime + (m_iTaskReminders * m_iTutorialReminderTime)) < (lastMessageTime + std::chrono::milliseconds(m_iTaskReminders * m_iTutorialReminderTime)) <
PlatformTime::GetTickCount()) { time_util::clock::now()) {
// Reminder // Reminder
PopupMessageDetails* message = new PopupMessageDetails(); PopupMessageDetails* message = new PopupMessageDetails();
message->m_messageId = currentTask[m_CurrentState]->getDescriptionId(); message->m_messageId = currentTask[m_CurrentState]->getDescriptionId();
@ -2429,8 +2429,8 @@ bool Tutorial::setMessage(PopupMessageDetails* message) {
m_lastMessageState == m_CurrentState && m_lastMessageState == m_CurrentState &&
message->isSameContent(m_lastMessage) && message->isSameContent(m_lastMessage) &&
(!message->m_isReminder || (!message->m_isReminder ||
((lastMessageTime + m_iTutorialReminderTime) > ((lastMessageTime + std::chrono::milliseconds(m_iTutorialReminderTime)) >
PlatformTime::GetTickCount() && time_util::clock::now() &&
message->m_isReminder))) { message->m_isReminder))) {
delete message; delete message;
return false; return false;
@ -2441,7 +2441,7 @@ bool Tutorial::setMessage(PopupMessageDetails* message) {
m_lastMessageState = m_CurrentState; m_lastMessageState = m_CurrentState;
if (!message->m_replaceCurrent) if (!message->m_replaceCurrent)
lastMessageTime = PlatformTime::GetTickCount(); lastMessageTime = time_util::clock::now();
std::wstring text; std::wstring text;
if (!message->m_messageString.empty()) { if (!message->m_messageString.empty()) {
@ -2501,7 +2501,7 @@ bool Tutorial::setMessage(PopupMessageDetails* message) {
} else if ((m_lastMessage != nullptr && } else if ((m_lastMessage != nullptr &&
m_lastMessage->m_messageId != m_lastMessage->m_messageId !=
-1)) //&& (lastMessageTime + m_iTutorialReminderTime ) > -1)) //&& (lastMessageTime + m_iTutorialReminderTime ) >
// PlatformTime::GetTickCount() ) // time_util::tick_count32() )
{ {
// This should cause the popup to dissappear // This should cause the popup to dissappear
TutorialPopupInfo popupInfo; TutorialPopupInfo popupInfo;
@ -2524,17 +2524,17 @@ bool Tutorial::setMessage(TutorialHint* hint, PopupMessageDetails* message) {
app.GetGameSettings(m_iPad, eGameSetting_DisplayHUD)); app.GetGameSettings(m_iPad, eGameSetting_DisplayHUD));
bool messageShown = false; bool messageShown = false;
std::uint32_t time = PlatformTime::GetTickCount(); auto now = time_util::clock::now();
if (message != nullptr && (message->m_forceDisplay || hintsOn) && if (message != nullptr && (message->m_forceDisplay || hintsOn) &&
(!message->m_delay || (!message->m_delay ||
((m_hintDisplayed && ((m_hintDisplayed &&
(time - m_lastHintDisplayedTime) > m_iTutorialHintDelayTime) || (now - m_lastHintDisplayedTime) > std::chrono::milliseconds(m_iTutorialHintDelayTime)) ||
(!m_hintDisplayed && (!m_hintDisplayed &&
(time - lastMessageTime) > m_iTutorialMinimumDisplayMessageTime)))) { (now - lastMessageTime) > std::chrono::milliseconds(m_iTutorialMinimumDisplayMessageTime))))) {
messageShown = setMessage(message); messageShown = setMessage(message);
if (messageShown) { if (messageShown) {
m_lastHintDisplayedTime = time; m_lastHintDisplayedTime = now;
m_hintDisplayed = true; m_hintDisplayed = true;
if (hint != nullptr) setHintCompleted(hint); if (hint != nullptr) setHintCompleted(hint);
} }
@ -2559,8 +2559,8 @@ void Tutorial::showTutorialPopup(bool show) {
if (!show) { if (!show) {
if (currentTask[m_CurrentState] != nullptr && if (currentTask[m_CurrentState] != nullptr &&
(!currentTask[m_CurrentState]->AllowFade() || (!currentTask[m_CurrentState]->AllowFade() ||
(lastMessageTime + m_iTutorialDisplayMessageTime) > (lastMessageTime + std::chrono::milliseconds(m_iTutorialDisplayMessageTime)) >
PlatformTime::GetTickCount())) { time_util::clock::now())) {
uiTempDisabled = true; uiTempDisabled = true;
} }
ui.SetTutorialVisible(m_iPad, show); ui.SetTutorialVisible(m_iPad, show);

View file

@ -1,5 +1,6 @@
#pragma once #pragma once
// using namespace std; // using namespace std;
#include <chrono>
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include <ranges> #include <ranges>
@ -8,6 +9,8 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "console_helpers/Timer.h"
#include "app/common/src/Tutorial/Constraints/TutorialConstraint.h" #include "app/common/src/Tutorial/Constraints/TutorialConstraint.h"
#include "app/common/src/Tutorial/Hints/TutorialHint.h" #include "app/common/src/Tutorial/Hints/TutorialHint.h"
#include "app/common/src/Tutorial/Tasks/TutorialTask.h" #include "app/common/src/Tutorial/Tasks/TutorialTask.h"
@ -87,7 +90,7 @@ private:
bool m_bSceneIsSplitscreen; bool m_bSceneIsSplitscreen;
bool m_bHasTickedOnce; bool m_bHasTickedOnce;
int m_firstTickTime; time_util::time_point m_firstTickTime;
protected: protected:
std::unordered_map<int, TutorialMessage*> messages; std::unordered_map<int, TutorialMessage*> messages;
@ -108,8 +111,8 @@ protected:
// D3DXVECTOR3 m_OriginalPosition; // D3DXVECTOR3 m_OriginalPosition;
public: public:
std::uint32_t lastMessageTime; time_util::time_point lastMessageTime;
std::uint32_t m_lastHintDisplayedTime; time_util::time_point m_lastHintDisplayedTime;
private: private:
PopupMessageDetails* m_lastMessage; PopupMessageDetails* m_lastMessage;

View file

@ -63,7 +63,7 @@ void TutorialMode::tick() {
/* /*
if( tutorial.m_allTutorialsComplete && (tutorial.lastMessageTime + if( tutorial.m_allTutorialsComplete && (tutorial.lastMessageTime +
m_iTutorialDisplayMessageTime) < PlatformTime::GetTickCount() ) m_iTutorialDisplayMessageTime) < time_util::tick_count32() )
{ {
// Exit tutorial // Exit tutorial
minecraft->gameMode = new SurvivalMode( this ); minecraft->gameMode = new SurvivalMode( this );

View file

@ -39,8 +39,8 @@
#include "UIFontData.h" #include "UIFontData.h"
#include "XboxStubs.h" #include "XboxStubs.h"
#include "console_helpers/C4JThread.h" #include "console_helpers/C4JThread.h"
#include "console_helpers/PerformanceTimer.h" #include "console_helpers/Timer.h"
#include "console_helpers/PlatformTime.h"
#include "console_helpers/StringHelpers.h" #include "console_helpers/StringHelpers.h"
#include "java/System.h" #include "java/System.h"
@ -235,7 +235,7 @@ UIController::UIController() {
m_bMenuToBeClosed[i] = false; m_bMenuToBeClosed[i] = false;
for (unsigned int key = 0; key <= ACTION_MAX_MENU; ++key) { for (unsigned int key = 0; key <= ACTION_MAX_MENU; ++key) {
m_actionRepeatTimer[i][key] = 0; m_actionRepeatTimer[i][key] = {};
} }
} }
@ -627,7 +627,6 @@ void UIController::ReloadSkin() {
m_reloadSkinThread = m_reloadSkinThread =
new C4JThread(reloadSkinThreadProc, (void*)this, "Reload skin thread"); new C4JThread(reloadSkinThreadProc, (void*)this, "Reload skin thread");
m_reloadSkinThread->setProcessor(CPU_CORE_UI_SCENE);
// Navigate to the timer scene so that we can display something while the // Navigate to the timer scene so that we can display something while the
// loading is happening // loading is happening
@ -776,19 +775,19 @@ void UIController::handleKeyPress(unsigned int iPad, unsigned int key) {
if (pressed) { if (pressed) {
// Start repeat timer // Start repeat timer
m_actionRepeatTimer[iPad][key] = m_actionRepeatTimer[iPad][key] =
PlatformTime::GetTickCount() + UI_REPEAT_KEY_DELAY_MS; time_util::clock::now() + std::chrono::milliseconds(UI_REPEAT_KEY_DELAY_MS);
} else if (released) { } else if (released) {
// Stop repeat timer // Stop repeat timer
m_actionRepeatTimer[iPad][key] = 0; m_actionRepeatTimer[iPad][key] = {};
} else if (down) { } else if (down) {
// Check is enough time has elapsed to be a repeat key // Check is enough time has elapsed to be a repeat key
std::uint32_t currentTime = PlatformTime::GetTickCount(); auto now = time_util::clock::now();
if (m_actionRepeatTimer[iPad][key] > 0 && if (m_actionRepeatTimer[iPad][key] != time_util::time_point{} &&
currentTime > m_actionRepeatTimer[iPad][key]) { now > m_actionRepeatTimer[iPad][key]) {
repeat = true; repeat = true;
pressed = true; pressed = true;
m_actionRepeatTimer[iPad][key] = m_actionRepeatTimer[iPad][key] =
currentTime + UI_REPEAT_KEY_REPEAT_RATE_MS; now + std::chrono::milliseconds(UI_REPEAT_KEY_REPEAT_RATE_MS);
} }
} }
@ -1275,7 +1274,7 @@ bool UIController::NavigateToScene(int iPad, EUIScene scene, void* initData,
} }
} }
PerformanceTimer timer; time_util::Timer timer;
bool success; bool success;
{ {
@ -1287,7 +1286,8 @@ bool UIController::NavigateToScene(int iPad, EUIScene scene, void* initData,
setFullscreenMenuDisplayed(true); setFullscreenMenuDisplayed(true);
} }
timer.PrintElapsedTime(L"Navigate to scene"); std::println(stderr, "TIMER: Navigate to scene: Elapsed time {:.6f}",
timer.elapsed_seconds());
return success; return success;
// return true; // return true;
@ -1404,9 +1404,8 @@ UIScene* UIController::GetTopScene(int iPad, EUILayer layer, EUIGroup group) {
size_t UIController::RegisterForCallbackId(UIScene* scene) { size_t UIController::RegisterForCallbackId(UIScene* scene) {
std::lock_guard<std::mutex> lock(m_registeredCallbackScenesCS); std::lock_guard<std::mutex> lock(m_registeredCallbackScenesCS);
size_t newId = PlatformTime::GetTickCount(); static std::atomic<std::uint32_t> s_nextId{1};
newId &= 0xFFFFFF; // Chop off the top byte, we don't need any more size_t newId = s_nextId.fetch_add(1, std::memory_order_relaxed) & 0xFFFFFF;
// accuracy than that
newId |= (scene->getSceneType() newId |= (scene->getSceneType()
<< 24); // Add in the scene's type to help keep this unique << 24); // Add in the scene's type to help keep this unique
m_registeredCallbackScenes[newId] = scene; m_registeredCallbackScenes[newId] = scene;

View file

@ -8,6 +8,8 @@
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include "console_helpers/Timer.h"
#ifdef __linux__ #ifdef __linux__
#include "app/linux/Iggy/include/iggy.h" #include "app/linux/Iggy/include/iggy.h"
#ifndef _ENABLEIGGY #ifndef _ENABLEIGGY
@ -60,7 +62,7 @@ private:
300; // How long from press until the first repeat 300; // How long from press until the first repeat
static const int UI_REPEAT_KEY_REPEAT_RATE_MS = static const int UI_REPEAT_KEY_REPEAT_RATE_MS =
100; // How long in between repeats 100; // How long in between repeats
std::uint32_t m_actionRepeatTimer[XUSER_MAX_COUNT][ACTION_MAX_MENU + 1]; time_util::time_point m_actionRepeatTimer[XUSER_MAX_COUNT][ACTION_MAX_MENU + 1];
float m_fScreenWidth; float m_fScreenWidth;
float m_fScreenHeight; float m_fScreenHeight;

View file

@ -1,14 +0,0 @@
#pragma once
#include <chrono>
#include <string>
class PerformanceTimer {
private:
std::chrono::steady_clock::time_point m_startTime;
public:
PerformanceTimer();
void Reset();
void PrintElapsedTime(const std::wstring& description);
};

View file

@ -1,38 +0,0 @@
#pragma once
#include <chrono>
#include <cstdint>
// Portable replacements for Win32 time APIs.
// GetTickCount() → PlatformTime::GetTickCount()
// QueryPerformanceCounter() → PlatformTime::QueryPerformanceCounter()
// QueryPerformanceFrequency() → PlatformTime::QueryPerformanceFrequency()
namespace PlatformTime {
// Returns milliseconds since an unspecified epoch (like Win32 GetTickCount).
inline std::uint32_t GetTickCount() {
auto now = std::chrono::steady_clock::now().time_since_epoch();
return static_cast<std::uint32_t>(
std::chrono::duration_cast<std::chrono::milliseconds>(now).count());
}
// High-resolution counter value (like Win32 QueryPerformanceCounter).
// Returns a count in ticks of steady_clock.
inline std::int64_t QueryPerformanceCounter() {
return std::chrono::steady_clock::now().time_since_epoch().count();
}
// Ticks per second for the high-resolution counter.
inline std::int64_t QueryPerformanceFrequency() {
return static_cast<std::int64_t>(std::chrono::steady_clock::period::den) /
static_cast<std::int64_t>(std::chrono::steady_clock::period::num);
}
// Elapsed seconds between two counter values.
inline double ElapsedSeconds(std::int64_t start, std::int64_t end) {
return static_cast<double>(end - start) /
static_cast<double>(QueryPerformanceFrequency());
}
} // namespace PlatformTime

View file

@ -0,0 +1,107 @@
#pragma once
#include <chrono>
#include <cstdint>
#include <cstdio>
#include <print>
#include <source_location>
#include <string_view>
namespace time_util {
using clock = std::chrono::steady_clock;
using time_point = clock::time_point;
template <typename T>
concept Duration = requires { typename T::rep; typename T::period; };
namespace detail {
[[nodiscard]] constexpr auto base_name(std::string_view path) noexcept
-> std::string_view {
const auto pos = path.find_last_of("/\\");
return pos == std::string_view::npos ? path : path.substr(pos + 1);
}
} // namespace detail
class Timer final {
public:
Timer() noexcept : start_(clock::now()) {}
void reset() noexcept { start_ = clock::now(); }
[[nodiscard]] auto elapsed() const noexcept -> clock::duration {
return clock::now() - start_;
}
template <Duration D = std::chrono::duration<double>>
[[nodiscard]] auto elapsed_as() const noexcept -> D {
return std::chrono::duration_cast<D>(elapsed());
}
[[nodiscard]] auto elapsed_seconds() const noexcept -> double {
return elapsed_as<std::chrono::duration<double>>().count();
}
[[nodiscard]] auto elapsed_millis() const noexcept -> double {
return elapsed_as<std::chrono::duration<double, std::milli>>().count();
}
private:
time_point start_;
};
class [[nodiscard]] ScopedTimer final {
public:
explicit ScopedTimer(
std::string_view name,
std::source_location where = std::source_location::current())
: name_(name),
file_(detail::base_name(where.file_name())),
line_(where.line()) {}
template <Duration D>
ScopedTimer(
std::string_view name,
D min_duration_to_log,
std::source_location where = std::source_location::current())
: name_(name),
file_(detail::base_name(where.file_name())),
line_(where.line()),
min_duration_to_log_(
std::chrono::duration_cast<clock::duration>(min_duration_to_log)) {
}
~ScopedTimer() noexcept {
const auto elapsed = timer_.elapsed();
if (elapsed < min_duration_to_log_) return;
const auto ms =
std::chrono::duration<double, std::milli>(elapsed).count();
try {
name_.empty()
? std::println(stderr, "[TIMER] {:.3f} ms ({}:{})",
ms, file_, line_)
: std::println(stderr, "[TIMER] {} - {:.3f} ms ({}:{})",
name_, ms, file_, line_);
} catch (...) {
std::fprintf(stderr, "[TIMER] %.3f ms\n", ms);
}
}
ScopedTimer(const ScopedTimer&) = delete;
auto operator=(const ScopedTimer&) -> ScopedTimer& = delete;
ScopedTimer(ScopedTimer&&) = delete;
auto operator=(ScopedTimer&&) -> ScopedTimer& = delete;
private:
std::string_view name_;
std::string_view file_;
std::uint_least32_t line_;
clock::duration min_duration_to_log_{clock::duration::zero()};
Timer timer_;
};
} // namespace time_util

View file

@ -1,8 +1,6 @@
console_helpers_sources = files( console_helpers_sources = files(
'src/C4JThread.cpp', 'src/C4JThread.cpp',
'src/PerformanceTimer.cpp',
'src/StringHelpers.cpp', 'src/StringHelpers.cpp',
'src/ThreadName.cpp',
'src/compression.cpp', 'src/compression.cpp',
) )

View file

@ -1,21 +0,0 @@
#include "console_helpers/PerformanceTimer.h"
#include <stdio.h>
#include <chrono>
#include <string>
PerformanceTimer::PerformanceTimer() { Reset(); }
void PerformanceTimer::Reset() {
m_startTime = std::chrono::steady_clock::now();
}
void PerformanceTimer::PrintElapsedTime(const std::wstring& description) {
const std::chrono::duration<float> elapsedTime =
std::chrono::steady_clock::now() - m_startTime;
fprintf(stderr, "TIMER: %ls: Elapsed time %f\n", description.c_str(),
elapsedTime.count());
}

View file

@ -271,7 +271,6 @@ Minecraft::Minecraft(Component* mouseComponent, Canvas* parent,
levelTickEventQueue = levelTickEventQueue =
new C4JThread::EventQueue(levelTickUpdateFunc, levelTickThreadInitFunc, new C4JThread::EventQueue(levelTickUpdateFunc, levelTickThreadInitFunc,
"LevelTick_EventQueuePoll"); "LevelTick_EventQueuePoll");
levelTickEventQueue->setProcessor(3);
levelTickEventQueue->setPriority(C4JThread::ThreadPriority::Normal); levelTickEventQueue->setPriority(C4JThread::ThreadPriority::Normal);
#endif #endif
} }
@ -1146,7 +1145,7 @@ void Minecraft::run_middle() {
} }
#endif #endif
} else { } else {
unsigned int uiTimeToAutosave = int64_t uiTimeToAutosave =
app.SecondsToAutosave(); app.SecondsToAutosave();
if (uiTimeToAutosave < 6) { if (uiTimeToAutosave < 6) {
@ -3960,7 +3959,7 @@ void Minecraft::fileDownloaded(const std::wstring& name, File* file) {
std::wstring Minecraft::gatherStats1() { std::wstring Minecraft::gatherStats1() {
// return levelRenderer->gatherStats1(); // return levelRenderer->gatherStats1();
return L"Time to autosave: " + return L"Time to autosave: " +
_toString<unsigned int>(app.SecondsToAutosave()) + L"s"; _toString<int64_t>(app.SecondsToAutosave()) + L"s";
} }
std::wstring Minecraft::gatherStats2() { std::wstring Minecraft::gatherStats2() {

View file

@ -35,7 +35,7 @@
#include "app/linux/Stubs/winapi_stubs.h" #include "app/linux/Stubs/winapi_stubs.h"
#include "MultiPlayerLevel.h" #include "MultiPlayerLevel.h"
#include "ReceivingLevelScreen.h" #include "ReceivingLevelScreen.h"
#include "console_helpers/PlatformTime.h" #include "console_helpers/Timer.h"
#include "console_helpers/StringHelpers.h" #include "console_helpers/StringHelpers.h"
#include "java/Class.h" #include "java/Class.h"
#include "java/InputOutputStream/ByteArrayInputStream.h" #include "java/InputOutputStream/ByteArrayInputStream.h"
@ -3575,8 +3575,8 @@ void ClientConnection::checkDeferredEntityLinkPackets(int newEntityId) {
bool remove = false; bool remove = false;
// Only consider recently deferred packets // Only consider recently deferred packets
int tickInterval = auto tickInterval =
PlatformTime::GetTickCount() - deferred->m_recievedTick; std::chrono::duration_cast<std::chrono::milliseconds>(time_util::clock::now() - deferred->m_recievedTick).count();
if (tickInterval < MAX_ENTITY_LINK_DEFERRAL_INTERVAL) { if (tickInterval < MAX_ENTITY_LINK_DEFERRAL_INTERVAL) {
// Note: we assume it's the destination entity // Note: we assume it's the destination entity
if (deferred->m_packet->destId == newEntityId) { if (deferred->m_packet->destId == newEntityId) {
@ -3599,6 +3599,6 @@ void ClientConnection::checkDeferredEntityLinkPackets(int newEntityId) {
ClientConnection::DeferredEntityLinkPacket::DeferredEntityLinkPacket( ClientConnection::DeferredEntityLinkPacket::DeferredEntityLinkPacket(
std::shared_ptr<SetEntityLinkPacket> packet) { std::shared_ptr<SetEntityLinkPacket> packet) {
m_recievedTick = PlatformTime::GetTickCount(); m_recievedTick = time_util::clock::now();
m_packet = packet; m_packet = packet;
} }

View file

@ -5,6 +5,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "console_helpers/Timer.h"
#include "platform/sdl2/Storage.h" #include "platform/sdl2/Storage.h"
#include "minecraft/network/Connection.h" #include "minecraft/network/Connection.h"
@ -216,7 +217,7 @@ private:
// 4J: Entity link packet deferred // 4J: Entity link packet deferred
class DeferredEntityLinkPacket { class DeferredEntityLinkPacket {
public: public:
uint32_t m_recievedTick; time_util::time_point m_recievedTick;
std::shared_ptr<SetEntityLinkPacket> m_packet; std::shared_ptr<SetEntityLinkPacket> m_packet;
DeferredEntityLinkPacket(std::shared_ptr<SetEntityLinkPacket> packet); DeferredEntityLinkPacket(std::shared_ptr<SetEntityLinkPacket> packet);

View file

@ -23,7 +23,7 @@
#include "app/linux/Linux_App.h" #include "app/linux/Linux_App.h"
#include "PlayerList.h" #include "PlayerList.h"
#include "Settings.h" #include "Settings.h"
#include "console_helpers/PlatformTime.h" #include "console_helpers/Timer.h"
#include "java/Class.h" #include "java/Class.h"
#include "java/File.h" #include "java/File.h"
#include "java/InputOutputStream/DataOutputStream.h" #include "java/InputOutputStream/DataOutputStream.h"
@ -102,7 +102,7 @@ int64_t MinecraftServer::s_tickStartTime = 0;
std::vector<INetworkPlayer*> MinecraftServer::s_sentTo; std::vector<INetworkPlayer*> MinecraftServer::s_sentTo;
#else #else
int MinecraftServer::s_slowQueuePlayerIndex = 0; int MinecraftServer::s_slowQueuePlayerIndex = 0;
int MinecraftServer::s_slowQueueLastTime = 0; time_util::time_point MinecraftServer::s_slowQueueLastTime = {};
bool MinecraftServer::s_slowQueuePacketSent = false; bool MinecraftServer::s_slowQueuePacketSent = false;
#endif #endif
@ -528,7 +528,6 @@ bool MinecraftServer::loadLevel(LevelStorageSource* storageSource,
new C4JThread(runPostUpdate, this, "Post processing", 256 * 1024); new C4JThread(runPostUpdate, this, "Post processing", 256 * 1024);
m_postUpdateTerminate = false; m_postUpdateTerminate = false;
m_postUpdateThread->setProcessor(CPU_CORE_POST_PROCESSING);
m_postUpdateThread->setPriority(C4JThread::ThreadPriority::AboveNormal); m_postUpdateThread->setPriority(C4JThread::ThreadPriority::AboveNormal);
m_postUpdateThread->run(); m_postUpdateThread->run();
@ -858,10 +857,7 @@ void MinecraftServer::saveGameRules() {
void MinecraftServer::Suspend() { void MinecraftServer::Suspend() {
m_suspending = true; m_suspending = true;
// Get the frequency of the timer time_util::Timer timer;
float fElapsedTime = 0.0f;
// Save the start time
auto qwTime = PlatformTime::QueryPerformanceCounter();
if (m_bLoaded && (!StorageManager.GetSaveDisabled())) { if (m_bLoaded && (!StorageManager.GetSaveDisabled())) {
if (players != nullptr) { if (players != nullptr) {
players->saveAll(nullptr); players->saveAll(nullptr);
@ -880,13 +876,10 @@ void MinecraftServer::Suspend() {
levels[0]->saveToDisc(nullptr, true); levels[0]->saveToDisc(nullptr, true);
} }
} }
auto qwNewTime = PlatformTime::QueryPerformanceCounter();
fElapsedTime =
static_cast<float>(PlatformTime::ElapsedSeconds(qwTime, qwNewTime));
m_suspending = false; m_suspending = false;
app.DebugPrintf("Suspend server: Elapsed time %f\n", fElapsedTime); app.DebugPrintf("Suspend server: Elapsed time %f\n",
static_cast<float>(timer.elapsed_seconds()));
} }
bool MinecraftServer::IsSuspending() { return m_suspending; } bool MinecraftServer::IsSuspending() { return m_suspending; }
@ -1644,9 +1637,9 @@ void MinecraftServer::chunkPacketManagement_PostTick() {}
bool MinecraftServer::chunkPacketManagement_CanSendTo(INetworkPlayer* player) { bool MinecraftServer::chunkPacketManagement_CanSendTo(INetworkPlayer* player) {
if (player == nullptr) return false; if (player == nullptr) return false;
int time = PlatformTime::GetTickCount(); auto now = time_util::clock::now();
if (player->GetSessionIndex() == s_slowQueuePlayerIndex && if (player->GetSessionIndex() == s_slowQueuePlayerIndex &&
(time - s_slowQueueLastTime) > MINECRAFT_SERVER_SLOW_QUEUE_DELAY) { (now - s_slowQueueLastTime) > std::chrono::milliseconds(MINECRAFT_SERVER_SLOW_QUEUE_DELAY)) {
// app.DebugPrintf("Slow queue OK for player #%d\n", // app.DebugPrintf("Slow queue OK for player #%d\n",
// player->GetSessionIndex()); // player->GetSessionIndex());
return true; return true;
@ -1664,15 +1657,15 @@ void MinecraftServer::chunkPacketManagement_PreTick() {}
void MinecraftServer::chunkPacketManagement_PostTick() { void MinecraftServer::chunkPacketManagement_PostTick() {
// 4J Ensure that the slow queue owner keeps cycling if it's not been used // 4J Ensure that the slow queue owner keeps cycling if it's not been used
// in a while // in a while
int time = PlatformTime::GetTickCount(); auto now = time_util::clock::now();
if ((s_slowQueuePacketSent) || ((time - s_slowQueueLastTime) > if ((s_slowQueuePacketSent) || ((now - s_slowQueueLastTime) >
(2 * MINECRAFT_SERVER_SLOW_QUEUE_DELAY))) { std::chrono::milliseconds(2 * MINECRAFT_SERVER_SLOW_QUEUE_DELAY))) {
// app.DebugPrintf("Considering cycling: (%d) %d - %d -> %d // app.DebugPrintf("Considering cycling: (%d) %d - %d -> %d
//> %d\n",s_slowQueuePacketSent, time, s_slowQueueLastTime, (time - //> %d\n",s_slowQueuePacketSent, time, s_slowQueueLastTime, (time -
// s_slowQueueLastTime), (2*MINECRAFT_SERVER_SLOW_QUEUE_DELAY)); // s_slowQueueLastTime), (2*MINECRAFT_SERVER_SLOW_QUEUE_DELAY));
MinecraftServer::cycleSlowQueueIndex(); MinecraftServer::cycleSlowQueueIndex();
s_slowQueuePacketSent = false; s_slowQueuePacketSent = false;
s_slowQueueLastTime = time; s_slowQueueLastTime = now;
} }
// else // else
// { // {

View file

@ -8,6 +8,7 @@
#include "ConsoleInputSource.h" #include "ConsoleInputSource.h"
#include "console_helpers/C4JThread.h" #include "console_helpers/C4JThread.h"
#include "console_helpers/Timer.h"
#include "minecraft/SharedConstants.h" #include "minecraft/SharedConstants.h"
#include "minecraft/world/level/chunk/ChunkSource.h" #include "minecraft/world/level/chunk/ChunkSource.h"
#include "minecraft/world/level/storage/ConsoleSaveFileIO/FileHeader.h" #include "minecraft/world/level/storage/ConsoleSaveFileIO/FileHeader.h"
@ -293,7 +294,7 @@ private:
static const int MAX_TICK_TIME_FOR_PACKET_SENDS = 35; static const int MAX_TICK_TIME_FOR_PACKET_SENDS = 35;
#else #else
static int s_slowQueuePlayerIndex; static int s_slowQueuePlayerIndex;
static int s_slowQueueLastTime; static time_util::time_point s_slowQueueLastTime;
static bool s_slowQueuePacketSent; static bool s_slowQueuePacketSent;
#endif #endif

View file

@ -7,7 +7,7 @@
#include "app/common/src/GameRules/LevelGeneration/LevelGenerationOptions.h" #include "app/common/src/GameRules/LevelGeneration/LevelGenerationOptions.h"
#include "app/linux/Linux_App.h" #include "app/linux/Linux_App.h"
#include "console_helpers/PlatformTime.h" #include "console_helpers/Timer.h"
#include "java/Random.h" #include "java/Random.h"
#include "minecraft/util/Mth.h" #include "minecraft/util/Mth.h"
#include "minecraft/world/entity/MobCategory.h" #include "minecraft/world/entity/MobCategory.h"
@ -102,8 +102,8 @@ RandomLevelSource::~RandomLevelSource() {
} }
int g_numPrepareHeightCalls = 0; int g_numPrepareHeightCalls = 0;
std::int64_t g_totalPrepareHeightsTime = 0; time_util::clock::duration g_totalPrepareHeightsTime{};
std::int64_t g_averagePrepareHeightsTime = 0; time_util::clock::duration g_averagePrepareHeightsTime{};
#if defined(_LARGE_WORLDS) #if defined(_LARGE_WORLDS)
@ -243,7 +243,6 @@ float RandomLevelSource::getHeightFalloff(int xxx, int zzz, int* pEMin) {
void RandomLevelSource::prepareHeights(int xOffs, int zOffs, void RandomLevelSource::prepareHeights(int xOffs, int zOffs,
std::vector<uint8_t>& blocks) { std::vector<uint8_t>& blocks) {
std::int64_t startTime;
int xChunks = 16 / CHUNK_WIDTH; int xChunks = 16 / CHUNK_WIDTH;
int yChunks = Level::genDepth / CHUNK_HEIGHT; int yChunks = Level::genDepth / CHUNK_HEIGHT;
int waterHeight = level->seaLevel; int waterHeight = level->seaLevel;
@ -265,7 +264,7 @@ void RandomLevelSource::prepareHeights(int xOffs, int zOffs,
buffer = getHeights(buffer, xOffs * xChunks, 0, zOffs * xChunks, xSize, buffer = getHeights(buffer, xOffs * xChunks, 0, zOffs * xChunks, xSize,
ySize, zSize, biomes); ySize, zSize, biomes);
startTime = PlatformTime::QueryPerformanceCounter(); time_util::Timer timer;
for (int xc = 0; xc < xChunks; xc++) { for (int xc = 0; xc < xChunks; xc++) {
for (int zc = 0; zc < xChunks; zc++) { for (int zc = 0; zc < xChunks; zc++) {
for (int yc = 0; yc < yChunks; yc++) { for (int yc = 0; yc < yChunks; yc++) {
@ -377,10 +376,8 @@ void RandomLevelSource::prepareHeights(int xOffs, int zOffs,
} }
} }
} }
auto endTime = PlatformTime::QueryPerformanceCounter();
auto timeInFunc = endTime - startTime;
g_numPrepareHeightCalls++; g_numPrepareHeightCalls++;
g_totalPrepareHeightsTime += timeInFunc; g_totalPrepareHeightsTime += timer.elapsed();
g_averagePrepareHeightsTime = g_averagePrepareHeightsTime =
g_totalPrepareHeightsTime / g_numPrepareHeightCalls; g_totalPrepareHeightsTime / g_numPrepareHeightCalls;
} }

View file

@ -19,7 +19,7 @@
#include "app/common/src/GameRules/LevelGeneration/LevelGenerationOptions.h" #include "app/common/src/GameRules/LevelGeneration/LevelGenerationOptions.h"
#include "app/linux/Linux_App.h" #include "app/linux/Linux_App.h"
#include "app/linux/Stubs/winapi_stubs.h" #include "app/linux/Stubs/winapi_stubs.h"
#include "console_helpers/PlatformTime.h" #include "console_helpers/Timer.h"
#include "console_helpers/StringHelpers.h" #include "console_helpers/StringHelpers.h"
#include "console_helpers/compression.h" #include "console_helpers/compression.h"
#include "java/File.h" #include "java/File.h"
@ -1282,10 +1282,7 @@ void ConsoleSaveFileSplit::Flush(bool autosave, bool updateThumbnail) {
m_autosave = autosave; m_autosave = autosave;
if (!m_autosave) processSubfilesForWrite(); if (!m_autosave) processSubfilesForWrite();
// Get the frequency of the timer time_util::Timer timer;
auto qwTime = PlatformTime::QueryPerformanceCounter();
auto qwNewTime = qwTime;
float fElapsedTime = 0.0f;
unsigned int fileSize = header.GetFileSize(); unsigned int fileSize = header.GetFileSize();
@ -1311,16 +1308,12 @@ void ConsoleSaveFileSplit::Flush(bool autosave, bool updateThumbnail) {
compLength = 0; compLength = 0;
// Pre-calculate the buffer size required for the compressed data // Pre-calculate the buffer size required for the compressed data
// Save the start time timer.reset();
qwTime = PlatformTime::QueryPerformanceCounter();
Compression::getCompression()->Compress(nullptr, &compLength, pvSaveMem, Compression::getCompression()->Compress(nullptr, &compLength, pvSaveMem,
fileSize); fileSize);
qwNewTime = PlatformTime::QueryPerformanceCounter();
fElapsedTime = app.DebugPrintf("Check buffer size: Elapsed time %f\n",
static_cast<float>(PlatformTime::ElapsedSeconds(qwTime, qwNewTime)); static_cast<float>(timer.elapsed_seconds()));
app.DebugPrintf("Check buffer size: Elapsed time %f\n", fElapsedTime);
// We add 4 bytes to the start so that we can signal compressed data // We add 4 bytes to the start so that we can signal compressed data
// And another 4 bytes to store the decompressed data size // And another 4 bytes to store the decompressed data size
@ -1332,16 +1325,12 @@ void ConsoleSaveFileSplit::Flush(bool autosave, bool updateThumbnail) {
if (compData != nullptr) { if (compData != nullptr) {
// Re-compress all save data before we save it to disk // Re-compress all save data before we save it to disk
// Save the start time timer.reset();
qwTime = PlatformTime::QueryPerformanceCounter();
Compression::getCompression()->Compress(compData + 8, &compLength, Compression::getCompression()->Compress(compData + 8, &compLength,
pvSaveMem, fileSize); pvSaveMem, fileSize);
qwNewTime = PlatformTime::QueryPerformanceCounter();
fElapsedTime = app.DebugPrintf("Compress: Elapsed time %f\n",
static_cast<float>(PlatformTime::ElapsedSeconds(qwTime, qwNewTime)); static_cast<float>(timer.elapsed_seconds()));
app.DebugPrintf("Compress: Elapsed time %f\n", fElapsedTime);
memset(compData, 0, 8); memset(compData, 0, 8);
int saveVer = 0; int saveVer = 0;