Skip to content

Commit a69c7fc

Browse files
committed
Timing/clock improvements
1 parent 6abcf83 commit a69c7fc

File tree

3 files changed

+82
-33
lines changed

3 files changed

+82
-33
lines changed

src/headless/main.cpp

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@
2424

2525
using namespace OpenVic;
2626

27-
inline static void print_bytes(std::string_view prefix, const std::source_location& location = std::source_location::current()) {
27+
inline static void print_memory_usage(
28+
std::string_view prefix, std::source_location const& location = std::source_location::current()
29+
) {
2830
#ifdef DEBUG_ENABLED // memory tracking will return 0 without DEBUG_ENABLED
2931
Logger::info<std::string_view&, const char(&)[16], uint64_t&&, const char(&)[7]>(
3032
prefix, " Memory Usage: ", OpenVic::utility::MemoryTracker::get_memory_usage(), " Bytes", location
@@ -79,8 +81,12 @@ static void print_rgo(ProvinceInstance const& province) {
7981
using pathing_rng_t = std::mt19937;
8082
using pathing_rng_seed_t = pathing_rng_t::result_type;
8183

84+
using testing_clock_t = std::chrono::high_resolution_clock;
85+
using test_time_point_t = testing_clock_t::time_point;
86+
using test_duration_t = testing_clock_t::duration;
87+
8288
template<size_t TestCount>
83-
static std::chrono::nanoseconds run_pathing_test(AStarPathing& pathing, std::optional<pathing_rng_seed_t> seed) {
89+
static test_duration_t run_pathing_test(AStarPathing& pathing, std::optional<pathing_rng_seed_t> seed) {
8490
PointMap const& points = pathing.get_point_map();
8591

8692
if (!seed.has_value()) {
@@ -107,11 +113,11 @@ static std::chrono::nanoseconds run_pathing_test(AStarPathing& pathing, std::opt
107113
from_to_tests[index] = { from, to };
108114
}
109115

110-
auto start_time = std::chrono::high_resolution_clock::now();
116+
const test_time_point_t start_time = testing_clock_t::now();
111117
for (auto [index, pair] : from_to_tests | ranges::views::enumerate) {
112118
test_results[index] = pathing.get_id_path(pair.first.key(), pair.second.key());
113119
}
114-
auto end_time = std::chrono::high_resolution_clock::now();
120+
const test_time_point_t end_time = testing_clock_t::now();
115121

116122
for (auto [index, test] : test_results | ranges::views::enumerate) {
117123
Logger::info("-Start Test ", index + 1, "-");
@@ -162,7 +168,7 @@ static bool run_headless(fs::path const& root, memory::vector<memory::string>& m
162168
}
163169
);
164170

165-
print_bytes("Definition Setup");
171+
print_memory_usage("Definition Setup");
166172

167173
if (run_tests) {
168174
Testing testing { game_manager.get_definition_manager() };
@@ -177,15 +183,15 @@ static bool run_headless(fs::path const& root, memory::vector<memory::string>& m
177183
game_manager.get_definition_manager().get_history_manager().get_bookmark_manager().get_bookmark_by_index(0)
178184
);
179185

180-
print_bytes("Instance Setup");
186+
print_memory_usage("Instance Setup");
181187

182188
Logger::info("===== Starting game session... =====");
183189
ret &= game_manager.start_game_session();
184190

185191
// This triggers a gamestate update
186192
ret &= game_manager.update_clock();
187193

188-
print_bytes("Game Session Post-Start");
194+
print_memory_usage("Game Session Post-Start");
189195

190196
// TODO - REMOVE TEST CODE
191197
Logger::info("===== Ranking system test... =====");
@@ -232,29 +238,60 @@ static bool run_headless(fs::path const& root, memory::vector<memory::string>& m
232238
// Set to std::nullopt to use a different random seed on each run
233239
static constexpr std::optional<pathing_rng_seed_t> LAND_SEED = 1836, SEA_SEED = 1861;
234240

241+
using test_time_units_t = std::chrono::milliseconds;
242+
235243
Logger::info("===== Land Pathfinding test... =====");
236-
std::chrono::nanoseconds ns = run_pathing_test<TESTS>(
244+
test_duration_t duration = std::chrono::duration_cast<test_time_units_t>(run_pathing_test<TESTS>(
237245
game_manager.get_instance_manager()->get_map_instance().get_land_pathing(), LAND_SEED
238-
);
239-
Logger::info("Ran ", TESTS, " land pathing tests in ", ns);
246+
));
247+
Logger::info("Ran ", TESTS, " land pathing tests in ", duration);
240248

241249
Logger::info("===== Sea Pathfinding test... =====");
242-
ns = run_pathing_test<TESTS>(
250+
duration = std::chrono::duration_cast<test_time_units_t>(run_pathing_test<TESTS>(
243251
game_manager.get_instance_manager()->get_map_instance().get_sea_pathing(), SEA_SEED
244-
);
245-
Logger::info("Ran ", TESTS, " sea pathing tests in ", ns);
252+
));
253+
Logger::info("Ran ", TESTS, " sea pathing tests in ", duration);
246254
}
247255

248256
if (ret) {
257+
static constexpr size_t TICK_COUNT = 10;
258+
249259
Logger::info("===== Game Tick test... =====");
250260
size_t ticks_passed = 0;
251-
auto start_time = std::chrono::high_resolution_clock::now();
252-
while (ticks_passed++ < 10) {
261+
test_duration_t min_tick_duration = test_duration_t::max(), max_tick_duration = test_duration_t::min(),
262+
total_tick_duration;
263+
const test_time_point_t start_time = testing_clock_t::now();
264+
while (++ticks_passed < TICK_COUNT) {
265+
const test_time_point_t tick_start = testing_clock_t::now();
253266
game_manager.get_instance_manager()->force_tick_and_update();
254-
print_bytes("Tick Finished");
267+
const test_time_point_t tick_end = testing_clock_t::now();
268+
269+
const test_duration_t tick_duration = tick_end - tick_start;
270+
271+
min_tick_duration = std::min(min_tick_duration, tick_duration);
272+
max_tick_duration = std::max(max_tick_duration, tick_duration);
273+
274+
total_tick_duration += tick_duration;
275+
276+
print_memory_usage(fmt::format("Tick {} finished", ticks_passed));
277+
}
278+
const test_time_point_t end_time = testing_clock_t::now();
279+
const test_duration_t duration = end_time - start_time;
280+
281+
if (ticks_passed != 0 && duration != test_duration_t::zero()) {
282+
const test_duration_t tick_tps = total_tick_duration / ticks_passed;
283+
const test_duration_t total_tps = duration / ticks_passed;
284+
Logger::info(
285+
"Ran ", ticks_passed, " / ", TICK_COUNT, " ticks, total time ", duration, " at, ", total_tps,
286+
" per tick, tick time only ", total_tick_duration, " at ", tick_tps, " per tick. Tick lengths ranged from ",
287+
min_tick_duration, " to ", max_tick_duration, "."
288+
);
289+
} else {
290+
Logger::error(
291+
"No ticks passed (", ticks_passed, ", expected ", TICK_COUNT, ") or zero duration measured (", duration, ")!"
292+
);
293+
ret = false;
255294
}
256-
auto end_time = std::chrono::high_resolution_clock::now();
257-
Logger::info("Ran ", --ticks_passed, " ticks in ", end_time - start_time);
258295
}
259296

260297
Logger::info("===== Ending game session... =====");
@@ -283,7 +320,8 @@ int main(int argc, char const* argv[]) {
283320
* message and the help text are displayed, along with returning false to signify the program should exit.
284321
*/
285322
const auto _read = [&root, &argn, argc, argv, program_name](
286-
std::string_view command, std::string_view path_use, auto path_transform) -> bool {
323+
std::string_view command, std::string_view path_use, std::invocable<fs::path> auto path_transform
324+
) -> bool {
287325
if (root.empty()) {
288326
if (++argn < argc) {
289327
char const* path = argv[argn];

src/openvic-simulation/misc/SimulationClock.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ SimulationClock::SimulationClock(
1111
reset();
1212
}
1313

14+
SimulationClock::time_point_t SimulationClock::get_now() const {
15+
return clock_t::now();
16+
}
17+
1418
void SimulationClock::set_paused(bool new_paused) {
1519
if (paused != new_paused) {
1620
toggle_paused();
@@ -46,25 +50,23 @@ bool SimulationClock::can_decrease_simulation_speed() const {
4650

4751
void SimulationClock::conditionally_advance_game() {
4852
if (!paused) {
49-
const time_point_t current_time = std::chrono::high_resolution_clock::now();
50-
const std::chrono::milliseconds time_since_last_tick =
51-
std::chrono::duration_cast<std::chrono::milliseconds>(current_time - last_tick_time);
52-
if (time_since_last_tick >= GAME_SPEEDS[current_speed]) {
53-
last_tick_time = current_time;
53+
const time_point_t current_time = get_now();
54+
if (next_tick_time <= current_time) {
55+
next_tick_time = current_time + GAME_SPEEDS[current_speed];
5456
tick_function();
5557
}
5658
}
5759
update_function();
5860
}
5961

6062
void SimulationClock::force_advance_game() {
61-
last_tick_time = std::chrono::high_resolution_clock::now();
63+
next_tick_time = get_now() + GAME_SPEEDS[current_speed];
6264
tick_function();
6365
update_function();
6466
}
6567

6668
void SimulationClock::reset() {
6769
paused = true;
6870
current_speed = 0;
69-
last_tick_time = std::chrono::high_resolution_clock::now();
71+
next_tick_time = get_now();
7072
}

src/openvic-simulation/misc/SimulationClock.hpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,32 @@ namespace OpenVic {
1313
public:
1414
using tick_function_t = fu2::function_base<true, true, fu2::capacity_can_hold<void*>, false, false, void()>;
1515
using update_function_t = fu2::function_base<true, true, fu2::capacity_can_hold<void*>, false, false, void()>;
16+
17+
using clock_t = std::chrono::high_resolution_clock;
18+
using time_point_t = clock_t::time_point;
19+
using duration_t = clock_t::duration;
20+
21+
static constexpr size_t NUM_SPEEDS = 5;
1622
using speed_t = int8_t;
23+
using speed_rates_t = std::array<duration_t, NUM_SPEEDS>;
1724

1825
/* Minimum number of milliseconds before the simulation advances
1926
* (in descending duration order, hence increasing speed order). */
20-
static constexpr std::chrono::milliseconds GAME_SPEEDS[] {
21-
std::chrono::milliseconds { 3000 }, std::chrono::milliseconds { 2000 }, std::chrono::milliseconds { 1000 },
22-
std::chrono::milliseconds { 100 }, std::chrono::milliseconds { 1 }
23-
};
27+
static constexpr speed_rates_t GAME_SPEEDS = []() constexpr -> speed_rates_t {
28+
using namespace std::chrono_literals;
29+
return {
30+
3s, 2s, 1s, 100ms, 1ms
31+
};
32+
}();
2433
static constexpr speed_t MIN_SPEED = 0, MAX_SPEED = std::size(GAME_SPEEDS) - 1;
2534

2635
private:
27-
using time_point_t = std::chrono::time_point<std::chrono::high_resolution_clock>;
28-
2936
/* Advance simulation (triggered while unpaused at interval determined by speed). */
3037
tick_function_t tick_function;
3138
/* Refresh game state (triggered with every call to conditionally_advance_game). */
3239
update_function_t update_function;
3340

34-
time_point_t last_tick_time;
41+
time_point_t next_tick_time;
3542
speed_t PROPERTY_CUSTOM_NAME(current_speed, get_simulation_speed, 0);
3643
bool PROPERTY_CUSTOM_PREFIX(paused, is, true);
3744

@@ -41,6 +48,8 @@ namespace OpenVic {
4148
tick_function_t new_tick_function, update_function_t new_update_function
4249
);
4350

51+
time_point_t get_now() const;
52+
4453
void set_paused(bool new_paused);
4554
void toggle_paused();
4655

0 commit comments

Comments
 (0)