#include <xtd/diagnostics/stopwatch>
#include <xtd/console>
#include <limits>
using namespace std;
class operations_timer {
public:
static void display_timer_properties() {
if (stopwatch::is_high_resolution())
console::write_line("Operations timed using the system's high-resolution performance counter.");
else
console::write_line("Operations timed using the standard date time.");
auto frequency = stopwatch::frequency();
console::write_line(" Timer frequency in ticks per second = {0}", frequency);
auto nanosec_per_tick = (1000
l * 1000
l * 1000
l) / frequency;
console::write_line(" Timer is accurate within {0} nanoseconds", nanosec_per_tick);
}
static void time_operations() {
auto nanosec_per_tick = (1000
l * 1000
l * 1000
l) / stopwatch::frequency();
constexpr auto num_iterations = 10000;
auto operation_names = vector {"Operation: parse<int>(\"0\")", "Operation: try_parse<int>(\"0\")", "Operation: parse<int>(\"a\")", "Operation: try_parse<int>(\"a\")"};
for (auto operation = 0; operation <= 3; operation++) {
[[maybe_unused]]
auto num_rollovers = 0
l;
auto min_ticks = numeric_limits<long>::max();
auto index_fastest = -1;
auto index_slowest = -1;
auto time_10k_operations = stopwatch::start_new();
for (
auto i = 0;
i <= num_iterations;
i++) {
auto ticks_this_time = 0
l;
auto input_num = 0;
switch (operation) {
case 0:
time_per_parse = stopwatch::start_new();
try {
input_num = 0;
}
time_per_parse.stop();
ticks_this_time = time_per_parse.elapsed_ticks();
break;
case 1:
time_per_parse = stopwatch::start_new();
if (!try_parse<int>("0", input_num))
input_num = 0;
time_per_parse.stop();
ticks_this_time = time_per_parse.elapsed_ticks();
break;
case 2:
time_per_parse = stopwatch::start_new();
try {
input_num = 0;
}
time_per_parse.stop();
ticks_this_time = time_per_parse.elapsed_ticks();
break;
case 3:
time_per_parse = stopwatch::start_new();
input_num = 0;
time_per_parse.stop();
ticks_this_time = time_per_parse.elapsed_ticks();
break;
default:
break;
}
time_10k_operations.reset();
time_10k_operations.start();
} else {
if (max_ticks < ticks_this_time) {
max_ticks = ticks_this_time;
}
if (min_ticks > ticks_this_time) {
min_ticks = ticks_this_time;
}
num_ticks += ticks_this_time;
if (num_ticks < ticks_this_time) {
num_rollovers ++;
}
}
}
time_10k_operations.stop();
milli_sec = time_10k_operations.elapsed_milliseconds();
console::write_line();
console::write_line("{0} Summary:", operation_names[operation]);
console::write_line(" Slowest time: #{0}/{1} = {2} ticks", index_slowest, num_iterations, max_ticks);
console::write_line(" Fastest time: #{0}/{1} = {2} ticks", index_fastest, num_iterations, min_ticks);
console::write_line(" Average time: {0} ticks = {1} nanoseconds", num_ticks / num_iterations, (num_ticks * nanosec_per_tick) / num_iterations);
console::write_line(" Total time looping through {0} operations: {1} milliseconds", num_iterations, milli_sec);
}
}
};
auto main()->int {
operations_timer::display_timer_properties();
console::write_line();
console::write_line("Press the Enter key to begin:");
console::read_line();
console::write_line();
operations_timer::time_operations();
}