test_namespace.h 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #pragma once
  2. #include <library/cpp/bucket_quoter/bucket_quoter.h>
  3. #include <library/cpp/getopt/last_getopt.h>
  4. #include <util/thread/pool.h>
  5. #include <util/string/printf.h>
  6. #include <util/system/types.h>
  7. #include <util/stream/output.h>
  8. #include <util/datetime/base.h>
  9. #include <util/digest/fnv.h>
  10. #include <vector>
  11. #include <thread>
  12. #include <numeric>
  13. namespace NBucketQuoterTest {
  14. // thread unsafe
  15. struct TMockTimer {
  16. using TTime = i64;
  17. static constexpr ui64 Resolution = 1'000'000ull; // microseconds
  18. static TTime CurrentTime;
  19. static TMockTimer::TTime Now() {
  20. return CurrentTime;
  21. }
  22. static ui64 Duration(TMockTimer::TTime from, TMockTimer::TTime to) {
  23. return to - from;
  24. }
  25. static void Sleep(TDuration duration) {
  26. CurrentTime += duration.MicroSeconds();
  27. }
  28. };
  29. template <typename Timer>
  30. void Sleep(TDuration duration) {
  31. ::Sleep(duration);
  32. }
  33. template <>
  34. void Sleep<TMockTimer>(TDuration duration);
  35. template <class Timer>
  36. using QuoterTemplate = TBucketQuoter<i64, TMutex, Timer>;
  37. template<class Timer>
  38. struct TTestScenario {
  39. void operator () (TBucketQuoter<i64, TMutex, Timer>& quoter, ui64 work_time, i64 wait_time, ui64& store_result) const {
  40. typename Timer::TTime start = Timer::Now();
  41. work_time *= Timer::Resolution;
  42. while (Timer::Duration(start, Timer::Now()) < work_time) {
  43. while(!quoter.IsAvail()) {
  44. NBucketQuoterTest::Sleep<Timer>(TDuration::MicroSeconds(quoter.GetWaitTime()));
  45. }
  46. quoter.Use(1);
  47. ++store_result;
  48. if (wait_time != 0) {
  49. NBucketQuoterTest::Sleep<Timer>(TDuration::MicroSeconds(wait_time));
  50. }
  51. }
  52. }
  53. };
  54. template <class Timer, template <class TT> class Scenario>
  55. ui32 Run(ui64 thread_count, ui64 rps, ui64 seconds, i64 wait_time = 0) {
  56. TBucketQuoter<i64, TMutex, Timer> quoter(rps, rps);
  57. std::vector<std::thread> threads;
  58. std::vector<ui64> results;
  59. threads.reserve(thread_count);
  60. results.reserve(thread_count);
  61. for (ui32 i = 0; i < thread_count; ++i) {
  62. results.emplace_back(0);
  63. threads.emplace_back(Scenario<Timer>{}, std::ref(quoter), seconds, wait_time, std::ref(results.back()));
  64. }
  65. for (ui32 i = 0; i < thread_count; ++i) {
  66. threads[i].join();
  67. }
  68. return std::reduce(results.begin(), results.end(), 0, std::plus<>());
  69. }
  70. }