core_timing.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. // Copyright 2016 Dolphin Emulator Project / 2017 Dolphin Emulator Project
  2. // Licensed under GPLv2+
  3. // Refer to the license.txt file included.
  4. #include <catch2/catch.hpp>
  5. #include <array>
  6. #include <bitset>
  7. #include <cstdlib>
  8. #include <memory>
  9. #include <string>
  10. #include "common/file_util.h"
  11. #include "core/core.h"
  12. #include "core/core_timing.h"
  13. namespace {
  14. // Numbers are chosen randomly to make sure the correct one is given.
  15. constexpr std::array<u64, 5> CB_IDS{{42, 144, 93, 1026, UINT64_C(0xFFFF7FFFF7FFFF)}};
  16. constexpr int MAX_SLICE_LENGTH = 10000; // Copied from CoreTiming internals
  17. constexpr std::array<u64, 5> calls_order{{2, 0, 1, 4, 3}};
  18. std::array<s64, 5> delays{};
  19. std::bitset<CB_IDS.size()> callbacks_ran_flags;
  20. u64 expected_callback = 0;
  21. s64 lateness = 0;
  22. template <unsigned int IDX>
  23. void HostCallbackTemplate(u64 userdata, s64 nanoseconds_late) {
  24. static_assert(IDX < CB_IDS.size(), "IDX out of range");
  25. callbacks_ran_flags.set(IDX);
  26. REQUIRE(CB_IDS[IDX] == userdata);
  27. REQUIRE(CB_IDS[IDX] == CB_IDS[calls_order[expected_callback]]);
  28. delays[IDX] = nanoseconds_late;
  29. ++expected_callback;
  30. }
  31. u64 callbacks_done = 0;
  32. struct ScopeInit final {
  33. ScopeInit() {
  34. core_timing.SetMulticore(true);
  35. core_timing.Initialize([]() {});
  36. }
  37. ~ScopeInit() {
  38. core_timing.Shutdown();
  39. }
  40. Core::Timing::CoreTiming core_timing;
  41. };
  42. } // Anonymous namespace
  43. TEST_CASE("CoreTiming[BasicOrder]", "[core]") {
  44. ScopeInit guard;
  45. auto& core_timing = guard.core_timing;
  46. std::vector<std::shared_ptr<Core::Timing::EventType>> events{
  47. Core::Timing::CreateEvent("callbackA", HostCallbackTemplate<0>),
  48. Core::Timing::CreateEvent("callbackB", HostCallbackTemplate<1>),
  49. Core::Timing::CreateEvent("callbackC", HostCallbackTemplate<2>),
  50. Core::Timing::CreateEvent("callbackD", HostCallbackTemplate<3>),
  51. Core::Timing::CreateEvent("callbackE", HostCallbackTemplate<4>),
  52. };
  53. expected_callback = 0;
  54. core_timing.SyncPause(true);
  55. u64 one_micro = 1000U;
  56. for (std::size_t i = 0; i < events.size(); i++) {
  57. u64 order = calls_order[i];
  58. core_timing.ScheduleEvent(i * one_micro + 100U, events[order], CB_IDS[order]);
  59. }
  60. /// test pause
  61. REQUIRE(callbacks_ran_flags.none());
  62. core_timing.Pause(false); // No need to sync
  63. while (core_timing.HasPendingEvents())
  64. ;
  65. REQUIRE(callbacks_ran_flags.all());
  66. for (std::size_t i = 0; i < delays.size(); i++) {
  67. const double delay = static_cast<double>(delays[i]);
  68. const double micro = delay / 1000.0f;
  69. const double mili = micro / 1000.0f;
  70. printf("HostTimer Pausing Delay[%zu]: %.3f %.6f\n", i, micro, mili);
  71. }
  72. }
  73. #pragma optimize("", off)
  74. u64 TestTimerSpeed(Core::Timing::CoreTiming& core_timing) {
  75. u64 start = core_timing.GetGlobalTimeNs().count();
  76. u64 placebo = 0;
  77. for (std::size_t i = 0; i < 1000; i++) {
  78. placebo += core_timing.GetGlobalTimeNs().count();
  79. }
  80. u64 end = core_timing.GetGlobalTimeNs().count();
  81. return (end - start);
  82. }
  83. #pragma optimize("", on)
  84. TEST_CASE("CoreTiming[BasicOrderNoPausing]", "[core]") {
  85. ScopeInit guard;
  86. auto& core_timing = guard.core_timing;
  87. std::vector<std::shared_ptr<Core::Timing::EventType>> events{
  88. Core::Timing::CreateEvent("callbackA", HostCallbackTemplate<0>),
  89. Core::Timing::CreateEvent("callbackB", HostCallbackTemplate<1>),
  90. Core::Timing::CreateEvent("callbackC", HostCallbackTemplate<2>),
  91. Core::Timing::CreateEvent("callbackD", HostCallbackTemplate<3>),
  92. Core::Timing::CreateEvent("callbackE", HostCallbackTemplate<4>),
  93. };
  94. core_timing.SyncPause(true);
  95. core_timing.SyncPause(false);
  96. expected_callback = 0;
  97. u64 start = core_timing.GetGlobalTimeNs().count();
  98. u64 one_micro = 1000U;
  99. for (std::size_t i = 0; i < events.size(); i++) {
  100. u64 order = calls_order[i];
  101. core_timing.ScheduleEvent(i * one_micro + 100U, events[order], CB_IDS[order]);
  102. }
  103. u64 end = core_timing.GetGlobalTimeNs().count();
  104. const double scheduling_time = static_cast<double>(end - start);
  105. const double timer_time = static_cast<double>(TestTimerSpeed(core_timing));
  106. while (core_timing.HasPendingEvents())
  107. ;
  108. REQUIRE(callbacks_ran_flags.all());
  109. for (std::size_t i = 0; i < delays.size(); i++) {
  110. const double delay = static_cast<double>(delays[i]);
  111. const double micro = delay / 1000.0f;
  112. const double mili = micro / 1000.0f;
  113. printf("HostTimer No Pausing Delay[%zu]: %.3f %.6f\n", i, micro, mili);
  114. }
  115. const double micro = scheduling_time / 1000.0f;
  116. const double mili = micro / 1000.0f;
  117. printf("HostTimer No Pausing Scheduling Time: %.3f %.6f\n", micro, mili);
  118. printf("HostTimer No Pausing Timer Time: %.3f %.6f\n", timer_time / 1000.f,
  119. timer_time / 1000000.f);
  120. }