From a614c1ec05d7df971d9453856e4ef408abe16078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Thu, 13 Feb 2020 23:15:13 +0100 Subject: [PATCH 1/6] Add benchsimulate command Adds a new command, `benchsimulate`, that starts benchmarking UpdateLogic() function. --- src/openrct2/cmdline/BenchUpdate.cpp | 119 ++++++++++++++++++++++++++ src/openrct2/cmdline/CommandLine.hpp | 1 + src/openrct2/cmdline/RootCommands.cpp | 1 + 3 files changed, 121 insertions(+) create mode 100644 src/openrct2/cmdline/BenchUpdate.cpp diff --git a/src/openrct2/cmdline/BenchUpdate.cpp b/src/openrct2/cmdline/BenchUpdate.cpp new file mode 100644 index 0000000000..641c43c84a --- /dev/null +++ b/src/openrct2/cmdline/BenchUpdate.cpp @@ -0,0 +1,119 @@ +/***************************************************************************** + * Copyright (c) 2014-2020 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#include "CommandLine.hpp" + +#ifdef USE_BENCHMARK + +# include "../Context.h" +# include "../GameState.h" +# include "../OpenRCT2.h" +# include "../platform/platform.h" + +# include +# include +# include +# include + +using namespace OpenRCT2; + +static void BM_update(benchmark::State& state, const std::string& filename) +{ + std::unique_ptr context(CreateContext()); + if (context->Initialise()) + { + if (!filename.empty() && !context->LoadParkFromFile(filename)) + { + state.SkipWithError("Failed to load file!"); + } + + for (auto _ : state) + { + context->GetGameState()->UpdateLogic(); + } + state.SetItemsProcessed(state.iterations()); + } + else + { + state.SkipWithError("Context initialization failed."); + } +} + +static int cmdline_for_bench_sprite_sort(int argc, const char** argv) +{ + // Add a baseline test on an empty park + benchmark::RegisterBenchmark("baseline", BM_update, std::string{}); + + // Google benchmark does stuff to argv. It doesn't modify the pointees, + // but it wants to reorder the pointers, so present a copy of them. + std::vector argv_for_benchmark; + + // argv[0] is expected to contain the binary name. It's only for logging purposes, don't bother. + argv_for_benchmark.push_back(nullptr); + + // Extract file names from argument list. If there is no such file, consider it benchmark option. + for (int i = 0; i < argc; i++) + { + if (platform_file_exists(argv[i])) + { + // Register benchmark for sv6 if valid + benchmark::RegisterBenchmark(argv[i], BM_update, argv[i]); + } + else + { + argv_for_benchmark.push_back((char*)argv[i]); + } + } + // Update argc with all the changes made + argc = (int)argv_for_benchmark.size(); + ::benchmark::Initialize(&argc, &argv_for_benchmark[0]); + if (::benchmark::ReportUnrecognizedArguments(argc, &argv_for_benchmark[0])) + return -1; + + core_init(); + gOpenRCT2Headless = true; + + ::benchmark::RunSpecifiedBenchmarks(); + return 0; +} + +static exitcode_t HandleBenchUpdate(CommandLineArgEnumerator* argEnumerator) +{ + const char** argv = (const char**)argEnumerator->GetArguments() + argEnumerator->GetIndex(); + int32_t argc = argEnumerator->GetCount() - argEnumerator->GetIndex(); + int32_t result = cmdline_for_bench_sprite_sort(argc, argv); + if (result < 0) + { + return EXITCODE_FAIL; + } + return EXITCODE_OK; +} + +#else +static exitcode_t HandleBenchUpdate(CommandLineArgEnumerator* argEnumerator) +{ + log_error("Sorry, Google benchmark not enabled in this build"); + return EXITCODE_FAIL; +} +#endif // USE_BENCHMARK + +const CommandLineCommand CommandLine::BenchUpdateCommands[]{ +#ifdef USE_BENCHMARK + DefineCommand( + "", + "... [--benchmark_list_tests={true|false}] [--benchmark_filter=] [--benchmark_min_time=] " + "[--benchmark_repetitions=] [--benchmark_report_aggregates_only={true|false}] " + "[--benchmark_format=] [--benchmark_out=] [--benchmark_out_format=] " + "[--benchmark_color={auto|true|false}] [--benchmark_counters_tabular={true|false}] [--v=]", + nullptr, HandleBenchUpdate), + CommandTableEnd +#else + DefineCommand("", "*** SORRY NOT ENABLED IN THIS BUILD ***", nullptr, HandleBenchUpdate), CommandTableEnd +#endif // USE_BENCHMARK +}; diff --git a/src/openrct2/cmdline/CommandLine.hpp b/src/openrct2/cmdline/CommandLine.hpp index 665cb6dbe3..1df4fa3326 100644 --- a/src/openrct2/cmdline/CommandLine.hpp +++ b/src/openrct2/cmdline/CommandLine.hpp @@ -118,6 +118,7 @@ namespace CommandLine extern const CommandLineCommand SpriteCommands[]; extern const CommandLineCommand BenchGfxCommands[]; extern const CommandLineCommand BenchSpriteSortCommands[]; + extern const CommandLineCommand BenchUpdateCommands[]; extern const CommandLineCommand SimulateCommands[]; extern const CommandLineExample RootExamples[]; diff --git a/src/openrct2/cmdline/RootCommands.cpp b/src/openrct2/cmdline/RootCommands.cpp index a7d1a56c2a..b074e0b785 100644 --- a/src/openrct2/cmdline/RootCommands.cpp +++ b/src/openrct2/cmdline/RootCommands.cpp @@ -140,6 +140,7 @@ const CommandLineCommand CommandLine::RootCommands[] DefineSubCommand("sprite", CommandLine::SpriteCommands ), DefineSubCommand("benchgfx", CommandLine::BenchGfxCommands ), DefineSubCommand("benchspritesort", CommandLine::BenchSpriteSortCommands ), + DefineSubCommand("benchsimulate", CommandLine::BenchUpdateCommands ), DefineSubCommand("simulate", CommandLine::SimulateCommands ), CommandTableEnd }; From a3312547ae87c8139bc95aeb5e3d59a437257a1d Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Sun, 1 Mar 2020 17:18:24 +0100 Subject: [PATCH 2/6] Add BenchUpdate.cpp to Xcode project. --- OpenRCT2.xcodeproj/project.pbxproj | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index 72d4eb2437..9aef052167 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -238,6 +238,7 @@ 9308DA04209908090079EE96 /* TileElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 9308D9FC209908080079EE96 /* TileElement.h */; }; 9308DA05209908090079EE96 /* Surface.h in Headers */ = {isa = PBXBuildFile; fileRef = 9308D9FD209908090079EE96 /* Surface.h */; }; 930EEA6A24FC00950070314E /* ScenarioSelect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 930EEA6924FC00940070314E /* ScenarioSelect.cpp */; }; + 9329D520240C17C60054301C /* BenchUpdate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9329D51F240C17C60054301C /* BenchUpdate.cpp */; }; 932A211E22D73CFA00C57EDB /* GameActionCompat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 932A20CF22D73CEE00C57EDB /* GameActionCompat.cpp */; }; 932A211F22D73CFA00C57EDB /* GameActionRegistration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 932A20D322D73CEF00C57EDB /* GameActionRegistration.cpp */; }; 932A212022D73CFA00C57EDB /* GameAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 932A211C22D73CFA00C57EDB /* GameAction.cpp */; }; @@ -1325,6 +1326,9 @@ 9308D9FC209908080079EE96 /* TileElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TileElement.h; sourceTree = ""; }; 9308D9FD209908090079EE96 /* Surface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Surface.h; sourceTree = ""; }; 930EEA6924FC00940070314E /* ScenarioSelect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScenarioSelect.cpp; sourceTree = ""; }; + 9329D51F240C17C60054301C /* BenchUpdate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BenchUpdate.cpp; sourceTree = ""; }; + 932A20CD22D73CEE00C57EDB /* GuestSetNameAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = GuestSetNameAction.hpp; sourceTree = ""; }; + 932A20CE22D73CEE00C57EDB /* RideSetVehiclesAction.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = RideSetVehiclesAction.hpp; sourceTree = ""; }; 932A20CF22D73CEE00C57EDB /* GameActionCompat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GameActionCompat.cpp; sourceTree = ""; }; 932A20D322D73CEF00C57EDB /* GameActionRegistration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GameActionRegistration.cpp; sourceTree = ""; }; 932A20F522D73CF300C57EDB /* GameAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GameAction.h; sourceTree = ""; }; @@ -3122,6 +3126,7 @@ children = ( D48AFDB61EF78DBF0081C644 /* BenchGfxCommmands.cpp */, 4C724B2121F0AD790012ADD0 /* BenchSpriteSort.cpp */, + 9329D51F240C17C60054301C /* BenchUpdate.cpp */, F76C83631EC4E7CC00FA49E2 /* CommandLine.cpp */, F76C83641EC4E7CC00FA49E2 /* CommandLine.hpp */, F76C83651EC4E7CC00FA49E2 /* ConvertCommand.cpp */, @@ -4659,6 +4664,7 @@ C688785820289A0A0084B384 /* Balloon.cpp in Sources */, C688788820289ADE0084B384 /* X8DrawingEngine.cpp in Sources */, 66A10F6A257F1E1800DD651A /* LargeScenerySetColourAction.cpp in Sources */, + 9329D520240C17C60054301C /* BenchUpdate.cpp in Sources */, F775F5381EE3725C001F00E7 /* DummyAudioContext.cpp in Sources */, F775F5351EE35A89001F00E7 /* DummyUiContext.cpp in Sources */, 2A1F4FE1221FF4B0003CA045 /* Audio.cpp in Sources */, From 0410b3736945df548f1d6d68bfdb5358c7ec71de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Sat, 29 Aug 2020 22:47:37 +0200 Subject: [PATCH 3/6] Provide more detailed stats about simulation performance --- src/openrct2/GameState.cpp | 40 ++++++++++++++++++++++++- src/openrct2/GameState.h | 44 ++++++++++++++++++++++++++- src/openrct2/cmdline/BenchUpdate.cpp | 45 ++++++++++++++++++++++++++-- 3 files changed, 125 insertions(+), 4 deletions(-) diff --git a/src/openrct2/GameState.cpp b/src/openrct2/GameState.cpp index c13ca62b35..e61d81035a 100644 --- a/src/openrct2/GameState.cpp +++ b/src/openrct2/GameState.cpp @@ -12,6 +12,7 @@ #include "Context.h" #include "Editor.h" #include "Game.h" +#include "GameState.h" #include "GameStateSnapshots.h" #include "Input.h" #include "OpenRCT2.h" @@ -37,6 +38,7 @@ #include "world/Scenery.h" #include +#include using namespace OpenRCT2; using namespace OpenRCT2::Scripting; @@ -225,8 +227,17 @@ void GameState::Update() gInUpdateCode = false; } -void GameState::UpdateLogic() +void GameState::UpdateLogic(LogicTimings* timings) { + auto start_time = std::chrono::high_resolution_clock::now(); + + auto report_time = [timings, start_time](LogicTimePart part) { + if (timings != nullptr) + { + timings->TimingInfo[part][timings->CurrentIdx] = std::chrono::high_resolution_clock::now() - start_time; + } + }; + gScreenAge++; if (gScreenAge == 0) gScreenAge--; @@ -234,6 +245,7 @@ void GameState::UpdateLogic() GetContext()->GetReplayManager()->Update(); network_update(); + report_time(LogicTimePart::NetworkUpdate); if (network_get_mode() == NETWORK_MODE_SERVER) { @@ -277,33 +289,51 @@ void GameState::UpdateLogic() date_update(); _date = Date(static_cast(gDateMonthsElapsed), gDateMonthTicks); + report_time(LogicTimePart::Date); scenario_update(); + report_time(LogicTimePart::Scenario); climate_update(); + report_time(LogicTimePart::Climate); map_update_tiles(); + report_time(LogicTimePart::MapTiles); // Temporarily remove provisional paths to prevent peep from interacting with them map_remove_provisional_elements(); + report_time(LogicTimePart::MapStashProvisionalElements); map_update_path_wide_flags(); + report_time(LogicTimePart::MapPathWideFlags); peep_update_all(); + report_time(LogicTimePart::Peep); map_restore_provisional_elements(); + report_time(LogicTimePart::MapRestoreProvisionalElements); vehicle_update_all(); + report_time(LogicTimePart::Vehicle); sprite_misc_update_all(); + report_time(LogicTimePart::Misc); Ride::UpdateAll(); + report_time(LogicTimePart::Ride); if (!(gScreenFlags & SCREEN_FLAGS_EDITOR)) { _park->Update(_date); } + report_time(LogicTimePart::Park); research_update(); + report_time(LogicTimePart::Research); ride_ratings_update_all(); + report_time(LogicTimePart::RideRatings); ride_measurements_update(); + report_time(LogicTimePart::RideMeasurments); News::UpdateCurrentItem(); + report_time(LogicTimePart::News); map_animation_invalidate_all(); + report_time(LogicTimePart::MapAnimation); vehicle_sounds_update(); peep_update_crowd_noise(); climate_update_sound(); + report_time(LogicTimePart::Sounds); editor_open_windows_for_current_step(); // Update windows @@ -316,9 +346,11 @@ void GameState::UpdateLogic() } GameActions::ProcessQueue(); + report_time(LogicTimePart::GameActions); network_process_pending(); network_flush(); + report_time(LogicTimePart::NetworkFlush); gCurrentTicks++; gScenarioTicks++; @@ -332,7 +364,13 @@ void GameState::UpdateLogic() { hookEngine.Call(HOOK_TYPE::INTERVAL_DAY, true); } + report_time(LogicTimePart::Scripts); #endif + + if (timings != nullptr) + { + timings->CurrentIdx = (timings->CurrentIdx + 1) % LOGIC_UPDATE_MEASURMENTS_COUNT; + } } void GameState::CreateStateSnapshot() diff --git a/src/openrct2/GameState.h b/src/openrct2/GameState.h index 414bcc3eee..a5844696c2 100644 --- a/src/openrct2/GameState.h +++ b/src/openrct2/GameState.h @@ -11,12 +11,54 @@ #include "Date.h" +#include +#include +#include #include namespace OpenRCT2 { class Park; + // Information regarding various pieces of logic update + enum class LogicTimePart + { + NetworkUpdate, + Date, + Scenario, + Climate, + MapTiles, + MapStashProvisionalElements, + MapPathWideFlags, + Peep, + MapRestoreProvisionalElements, + Vehicle, + Misc, + Ride, + Park, + Research, + RideRatings, + RideMeasurments, + News, + MapAnimation, + Sounds, + GameActions, + NetworkFlush, + Scripts, + }; + + // ~6.5s at 40Hz + constexpr size_t LOGIC_UPDATE_MEASURMENTS_COUNT = 256; + + // In order not to cause allocations, collect multiple samples into single pre-allocated struct + using LogicTimingInfo = std::map, LOGIC_UPDATE_MEASURMENTS_COUNT>>; + + struct LogicTimings + { + LogicTimingInfo TimingInfo; + size_t CurrentIdx{}; + }; + /** * Class to update the state of the map and park. */ @@ -41,7 +83,7 @@ namespace OpenRCT2 void InitAll(int32_t mapSize); void Update(); - void UpdateLogic(); + void UpdateLogic(LogicTimings* timings = nullptr); private: void CreateStateSnapshot(); diff --git a/src/openrct2/cmdline/BenchUpdate.cpp b/src/openrct2/cmdline/BenchUpdate.cpp index 641c43c84a..b3fe767de3 100644 --- a/src/openrct2/cmdline/BenchUpdate.cpp +++ b/src/openrct2/cmdline/BenchUpdate.cpp @@ -14,6 +14,7 @@ # include "../Context.h" # include "../GameState.h" # include "../OpenRCT2.h" +# include "../platform/Platform2.h" # include "../platform/platform.h" # include @@ -33,11 +34,51 @@ static void BM_update(benchmark::State& state, const std::string& filename) state.SkipWithError("Failed to load file!"); } + std::vector timings(1); + timings.reserve(100); + int currentTimingIdx = 0; for (auto _ : state) { - context->GetGameState()->UpdateLogic(); + if (timings[currentTimingIdx].CurrentIdx == (LOGIC_UPDATE_MEASURMENTS_COUNT - 1)) + { + timings.resize(timings.size() + 1); + currentTimingIdx++; + } + LogicTimings* timingToUse = &timings[currentTimingIdx]; + context->GetGameState()->UpdateLogic(timingToUse); } state.SetItemsProcessed(state.iterations()); + auto accumulator = [timings](LogicTimePart part) -> double { + std::chrono::duration timesum; + for (const auto& timing : timings) + { + for (const auto& PartTime : timing.TimingInfo.at(part)) + timesum += PartTime; + } + return std::chrono::duration_cast(timesum).count(); + }; + state.counters["NetworkUpdateAcc_ms"] = accumulator(LogicTimePart::NetworkUpdate); + state.counters["DateAcc_ms"] = accumulator(LogicTimePart::Date); + state.counters["ScenarioAcc_ms"] = accumulator(LogicTimePart::Scenario); + state.counters["ClimateAcc_ms"] = accumulator(LogicTimePart::Climate); + state.counters["MapTilesAcc_ms"] = accumulator(LogicTimePart::MapTiles); + state.counters["MapStashProvisionalElementsAcc_ms"] = accumulator(LogicTimePart::MapStashProvisionalElements); + state.counters["MapPathWideFlagsAcc_ms"] = accumulator(LogicTimePart::MapPathWideFlags); + state.counters["PeepAcc_ms"] = accumulator(LogicTimePart::Peep); + state.counters["MapRestoreProvisionalElementsAcc_ms"] = accumulator(LogicTimePart::MapRestoreProvisionalElements); + state.counters["VehicleAcc_ms"] = accumulator(LogicTimePart::Vehicle); + state.counters["MiscAcc_ms"] = accumulator(LogicTimePart::Misc); + state.counters["RideAcc_ms"] = accumulator(LogicTimePart::Ride); + state.counters["ParkAcc_ms"] = accumulator(LogicTimePart::Park); + state.counters["ResearchAcc_ms"] = accumulator(LogicTimePart::Research); + state.counters["RideRatingsAcc_ms"] = accumulator(LogicTimePart::RideRatings); + state.counters["RideMeasurmentsAcc_ms"] = accumulator(LogicTimePart::RideMeasurments); + state.counters["NewsAcc_ms"] = accumulator(LogicTimePart::News); + state.counters["MapAnimationAcc_ms"] = accumulator(LogicTimePart::MapAnimation); + state.counters["SoundsAcc_ms"] = accumulator(LogicTimePart::Sounds); + state.counters["GameActionsAcc_ms"] = accumulator(LogicTimePart::GameActions); + state.counters["NetworkFlushAcc_ms"] = accumulator(LogicTimePart::NetworkFlush); + state.counters["ScriptsAcc_ms"] = accumulator(LogicTimePart::Scripts); } else { @@ -60,7 +101,7 @@ static int cmdline_for_bench_sprite_sort(int argc, const char** argv) // Extract file names from argument list. If there is no such file, consider it benchmark option. for (int i = 0; i < argc; i++) { - if (platform_file_exists(argv[i])) + if (Platform::FileExists(argv[i])) { // Register benchmark for sv6 if valid benchmark::RegisterBenchmark(argv[i], BM_update, argv[i]); From 6a6e58c088064f5f35f64a3e00ec82547b92da4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Sat, 29 Aug 2020 23:25:23 +0200 Subject: [PATCH 4/6] Update vcxproj --- src/openrct2/libopenrct2.vcxproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index ae1919630e..267d41f755 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -553,6 +553,7 @@ + From a8c3ca72edcc5818ba8b914c13a94b9ea8cee54f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Mon, 28 Dec 2020 23:53:37 +0100 Subject: [PATCH 5/6] Update to new style casts --- src/openrct2/cmdline/BenchUpdate.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/openrct2/cmdline/BenchUpdate.cpp b/src/openrct2/cmdline/BenchUpdate.cpp index b3fe767de3..db8cbbb371 100644 --- a/src/openrct2/cmdline/BenchUpdate.cpp +++ b/src/openrct2/cmdline/BenchUpdate.cpp @@ -86,7 +86,7 @@ static void BM_update(benchmark::State& state, const std::string& filename) } } -static int cmdline_for_bench_sprite_sort(int argc, const char** argv) +static int cmdline_for_bench_sprite_sort(int argc, const char* const* argv) { // Add a baseline test on an empty park benchmark::RegisterBenchmark("baseline", BM_update, std::string{}); @@ -108,11 +108,11 @@ static int cmdline_for_bench_sprite_sort(int argc, const char** argv) } else { - argv_for_benchmark.push_back((char*)argv[i]); + argv_for_benchmark.push_back(const_cast(argv[i])); } } // Update argc with all the changes made - argc = (int)argv_for_benchmark.size(); + argc = static_cast(argv_for_benchmark.size()); ::benchmark::Initialize(&argc, &argv_for_benchmark[0]); if (::benchmark::ReportUnrecognizedArguments(argc, &argv_for_benchmark[0])) return -1; @@ -126,7 +126,7 @@ static int cmdline_for_bench_sprite_sort(int argc, const char** argv) static exitcode_t HandleBenchUpdate(CommandLineArgEnumerator* argEnumerator) { - const char** argv = (const char**)argEnumerator->GetArguments() + argEnumerator->GetIndex(); + const char* const* argv = static_cast(argEnumerator->GetArguments()) + argEnumerator->GetIndex(); int32_t argc = argEnumerator->GetCount() - argEnumerator->GetIndex(); int32_t result = cmdline_for_bench_sprite_sort(argc, argv); if (result < 0) From deebd779a9d40307dbd3cfb10414d564613e3c3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Sun, 10 Jan 2021 13:33:53 +0100 Subject: [PATCH 6/6] Address review comments for benchsimulate --- src/openrct2/GameState.cpp | 2 +- src/openrct2/GameState.h | 7 ++++--- src/openrct2/cmdline/BenchUpdate.cpp | 11 ++++++----- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/openrct2/GameState.cpp b/src/openrct2/GameState.cpp index e61d81035a..595c31aa4b 100644 --- a/src/openrct2/GameState.cpp +++ b/src/openrct2/GameState.cpp @@ -369,7 +369,7 @@ void GameState::UpdateLogic(LogicTimings* timings) if (timings != nullptr) { - timings->CurrentIdx = (timings->CurrentIdx + 1) % LOGIC_UPDATE_MEASURMENTS_COUNT; + timings->CurrentIdx = (timings->CurrentIdx + 1) % LOGIC_UPDATE_MEASUREMENTS_COUNT; } } diff --git a/src/openrct2/GameState.h b/src/openrct2/GameState.h index a5844696c2..c4db3cf35c 100644 --- a/src/openrct2/GameState.h +++ b/src/openrct2/GameState.h @@ -13,8 +13,8 @@ #include #include -#include #include +#include namespace OpenRCT2 { @@ -48,10 +48,11 @@ namespace OpenRCT2 }; // ~6.5s at 40Hz - constexpr size_t LOGIC_UPDATE_MEASURMENTS_COUNT = 256; + constexpr size_t LOGIC_UPDATE_MEASUREMENTS_COUNT = 256; // In order not to cause allocations, collect multiple samples into single pre-allocated struct - using LogicTimingInfo = std::map, LOGIC_UPDATE_MEASURMENTS_COUNT>>; + using LogicTimingInfo = std::unordered_map< + LogicTimePart, std::array, LOGIC_UPDATE_MEASUREMENTS_COUNT>>; struct LogicTimings { diff --git a/src/openrct2/cmdline/BenchUpdate.cpp b/src/openrct2/cmdline/BenchUpdate.cpp index db8cbbb371..aa9f982bff 100644 --- a/src/openrct2/cmdline/BenchUpdate.cpp +++ b/src/openrct2/cmdline/BenchUpdate.cpp @@ -20,6 +20,7 @@ # include # include # include +# include # include using namespace OpenRCT2; @@ -39,7 +40,7 @@ static void BM_update(benchmark::State& state, const std::string& filename) int currentTimingIdx = 0; for (auto _ : state) { - if (timings[currentTimingIdx].CurrentIdx == (LOGIC_UPDATE_MEASURMENTS_COUNT - 1)) + if (timings[currentTimingIdx].CurrentIdx == (LOGIC_UPDATE_MEASUREMENTS_COUNT - 1)) { timings.resize(timings.size() + 1); currentTimingIdx++; @@ -52,8 +53,8 @@ static void BM_update(benchmark::State& state, const std::string& filename) std::chrono::duration timesum; for (const auto& timing : timings) { - for (const auto& PartTime : timing.TimingInfo.at(part)) - timesum += PartTime; + timesum = std::accumulate( + timing.TimingInfo.at(part).begin(), timing.TimingInfo.at(part).end(), std::chrono::duration()); } return std::chrono::duration_cast(timesum).count(); }; @@ -86,7 +87,7 @@ static void BM_update(benchmark::State& state, const std::string& filename) } } -static int cmdline_for_bench_sprite_sort(int argc, const char* const* argv) +static int CmdlineForBenchSpriteSort(int argc, const char* const* argv) { // Add a baseline test on an empty park benchmark::RegisterBenchmark("baseline", BM_update, std::string{}); @@ -128,7 +129,7 @@ static exitcode_t HandleBenchUpdate(CommandLineArgEnumerator* argEnumerator) { const char* const* argv = static_cast(argEnumerator->GetArguments()) + argEnumerator->GetIndex(); int32_t argc = argEnumerator->GetCount() - argEnumerator->GetIndex(); - int32_t result = cmdline_for_bench_sprite_sort(argc, argv); + int32_t result = CmdlineForBenchSpriteSort(argc, argv); if (result < 0) { return EXITCODE_FAIL;