From ba7ee0feb5c70c66895a53f60bb7020d0fa4afd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Watashi=20o=20y=C5=ABwaku=20suru?= Date: Sun, 8 Dec 2024 14:11:44 +0300 Subject: [PATCH] init --- .gitignore | 40 ++++++++++ CMakeLists.txt | 13 ++++ TimerResolutionMeasure/CMakeLists.txt | 7 ++ TimerResolutionMeasure/main.cpp | 101 ++++++++++++++++++++++++++ TimerResolutionMeasure/pch.h | 13 ++++ TimerResolutionMeasure/utils.cpp | 49 +++++++++++++ TimerResolutionMeasure/utils.h | 19 +++++ 7 files changed, 242 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 TimerResolutionMeasure/CMakeLists.txt create mode 100644 TimerResolutionMeasure/main.cpp create mode 100644 TimerResolutionMeasure/pch.h create mode 100644 TimerResolutionMeasure/utils.cpp create mode 100644 TimerResolutionMeasure/utils.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ad02912 --- /dev/null +++ b/.gitignore @@ -0,0 +1,40 @@ +# Ignore CMake-related files +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles/ +CMakeScripts/ +Testing/ +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps/ +CMakePresets.json +CMakeUserPresets.json + +# Ignore Visual Studio files +.vs/ +.vs2019/ +.vs2022/ +.idea/ + +# Ignore build directories +build/ +out/ + +# Ignore Visual Studio configuration files +*.user +*.userosscache +*.suo +*.sdf +*.opensdf +*.vssscc +*.vsscc + +# Ignore temporary files and backups +*.log +*.tmp +*.bak +*.swp +*~ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..410931d --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required (VERSION 3.8) + +if (POLICY CMP0141) + cmake_policy(SET CMP0141 NEW) + set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$,$>,$<$:EditAndContinue>,$<$:ProgramDatabase>>") +endif() + +project ("TimerResolutionMeasure" LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +add_subdirectory ("TimerResolutionMeasure") \ No newline at end of file diff --git a/TimerResolutionMeasure/CMakeLists.txt b/TimerResolutionMeasure/CMakeLists.txt new file mode 100644 index 0000000..dcfb92c --- /dev/null +++ b/TimerResolutionMeasure/CMakeLists.txt @@ -0,0 +1,7 @@ +add_executable (TimerResolutionMeasure "main.cpp" "pch.h" "utils.cpp" "utils.h") + +if (CMAKE_VERSION VERSION_GREATER 3.12) + set_property(TARGET TimerResolutionMeasure PROPERTY CXX_STANDARD 20) +endif() + +target_precompile_headers(TimerResolutionMeasure PRIVATE pch.h) \ No newline at end of file diff --git a/TimerResolutionMeasure/main.cpp b/TimerResolutionMeasure/main.cpp new file mode 100644 index 0000000..d438cb6 --- /dev/null +++ b/TimerResolutionMeasure/main.cpp @@ -0,0 +1,101 @@ +#include "pch.h" +#include "utils.h" +#include "conio.h" + +typedef NTSTATUS(NTAPI* NtQueryTimerResolution_t)(PULONG MinimumResolution, PULONG MaximumResolution, PULONG CurrentResolution); + +int main() { +#ifndef _DEBUG + if (!IsAdmin()) { + std::cerr << "Administrator privileges are required. The program will not function correctly and will now exit.\n"; + std::cout << "Press Enter to continue...\n"; + std::cin.get(); + return 0; + } +#else + std::cout << "[DEBUG] Administrator privilege check is skipped in debug mode.\n" + << " Note: Some functionality might not work correctly without elevated permissions.\n\n"; +#endif + + int sleep_duration = 1; + + AutoLibrary ntdll(L"ntdll.dll"); + NtQueryTimerResolution_t NtQueryTimerResolution = (NtQueryTimerResolution_t)GetProcAddress(ntdll.get(), "NtQueryTimerResolution"); + if (!NtQueryTimerResolution) { + std::cerr << "Failed to get address of NtQueryTimerResolution\n"; + return 1; + } + + ULONG minimum_resolution, maximum_resolution, current_resolution; + LARGE_INTEGER start, end, freq; + std::vector sleep_delays; + + if (!QueryPerformanceFrequency(&freq)) { + std::cerr << "QueryPerformanceFrequency failed\n"; + return 1; + } + + if (!SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS)) { + std::cerr << "SetPriorityClass failed\n"; + return 1; + } + + std::cout << "Press Enter to stop the cycle and calculate results...\n"; + + while (!_kbhit()) { + NTSTATUS status = NtQueryTimerResolution(&minimum_resolution, &maximum_resolution, ¤t_resolution); + if (!NT_SUCCESS(status)) { + std::cerr << "NtQueryTimerResolution failed\n"; + return 1; + } + + QueryPerformanceCounter(&start); + Sleep(sleep_duration); + QueryPerformanceCounter(&end); + + double delta_s = (double)(end.QuadPart - start.QuadPart) / freq.QuadPart; + double delta_ms = delta_s * 1000; + double delta_from_sleep = delta_ms - sleep_duration; + + std::cout << std::fixed << std::setprecision(4) + << "Resolution: " << (current_resolution / 10000.0) << "ms, " + << "Sleep(n=" << sleep_duration << ") slept " << delta_ms << "ms " + << "(delta: " << delta_from_sleep << ")\n"; + + sleep_delays.push_back(delta_from_sleep); + Sleep(1000); + } + + std::cin.get(); + sleep_delays.erase(sleep_delays.begin()); + + std::nth_element(sleep_delays.begin(), sleep_delays.begin() + sleep_delays.size() / 2, sleep_delays.end()); + std::sort(sleep_delays.begin(), sleep_delays.end()); + + size_t size = sleep_delays.size(); + + double sum = 0.0; + for (double delay : sleep_delays) { + sum += delay; + } + + double average = sum / size; + + double standard_deviation = 0.0; + for (double delay : sleep_delays) { + standard_deviation += pow(delay - average, 2); + } + + double stdev = sqrt(standard_deviation / (size - 1)); + + std::cout << "Results from " << size << " samples (excluding the first sample, which is often inaccurate)\n"; + std::cout << "Max: " << std::setw(10) << std::fixed << std::setprecision(4) << sleep_delays.back() << " ms\n"; + std::cout << "Avg: " << std::setw(10) << std::fixed << std::setprecision(4) << average << " ms\n"; + std::cout << "Min: " << std::setw(10) << std::fixed << std::setprecision(4) << sleep_delays.front() << " ms\n"; + std::cout << "STDEV: " << std::setw(10) << std::fixed << std::setprecision(4) << stdev << " ms\n"; + + std::cout << "\nPress Enter to exit..."; + std::cin.get(); + + return 0; +} \ No newline at end of file diff --git a/TimerResolutionMeasure/pch.h b/TimerResolutionMeasure/pch.h new file mode 100644 index 0000000..3fa5f80 --- /dev/null +++ b/TimerResolutionMeasure/pch.h @@ -0,0 +1,13 @@ +#ifndef PCH_H +#define PCH_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#endif //PCH_H \ No newline at end of file diff --git a/TimerResolutionMeasure/utils.cpp b/TimerResolutionMeasure/utils.cpp new file mode 100644 index 0000000..eb427d4 --- /dev/null +++ b/TimerResolutionMeasure/utils.cpp @@ -0,0 +1,49 @@ +#include "pch.h" +#include "utils.h" + +bool IsAdmin() { + bool admin = false; + HANDLE hToken = NULL; + + if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) { + TOKEN_ELEVATION elevation{}; + DWORD size; + if (GetTokenInformation(hToken, TokenElevation, &elevation, sizeof(elevation), &size)) { + admin = elevation.TokenIsElevated; + } + CloseHandle(hToken); + } + + return admin; +} + +AutoLibrary::AutoLibrary(const wchar_t* libName) { + handle = LoadLibraryW(libName); + if (!handle) { + DWORD error = GetLastError(); + std::wcerr << L"Failed to load library " << libName << L". Error code: " << error << std::endl; + throw std::runtime_error("Failed to load library"); + } +} + +AutoLibrary::~AutoLibrary() { + if (handle) { + FreeLibrary(handle); + } +} + +HMODULE AutoLibrary::get() const { + return handle; +} + +void calculateStatistics(const std::vector& delays, double& average, double& stdev) { + size_t size = delays.size(); + + double sum = std::accumulate(delays.begin(), delays.end(), 0.0); + double sq_sum = std::accumulate(delays.begin(), delays.end(), 0.0, [](double acc, double val) { + return acc + val * val; + }); + + average = sum / size; + stdev = std::sqrt(sq_sum / (size - 1) - average * average); +} \ No newline at end of file diff --git a/TimerResolutionMeasure/utils.h b/TimerResolutionMeasure/utils.h new file mode 100644 index 0000000..3799f0d --- /dev/null +++ b/TimerResolutionMeasure/utils.h @@ -0,0 +1,19 @@ +#pragma once + +#include "pch.h" + +bool IsAdmin(); + +class AutoLibrary { +public: + AutoLibrary(const wchar_t* libName); + ~AutoLibrary(); + HMODULE get() const; + + operator HMODULE() const { return handle; } + +private: + HMODULE handle; +}; + +void calculateStatistics(const std::vector& delays, double& average, double& stdev); \ No newline at end of file