interarrival.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /*
  2. *
  3. * Copyright 2015 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. #ifndef TEST_QPS_INTERARRIVAL_H
  19. #define TEST_QPS_INTERARRIVAL_H
  20. #include <chrono>
  21. #include <cmath>
  22. #include <random>
  23. #include <vector>
  24. #include <grpcpp/support/config.h>
  25. namespace grpc {
  26. namespace testing {
  27. // First create classes that define a random distribution
  28. // Note that this code does not include C++-specific random distribution
  29. // features supported in std::random. Although this would make this code easier,
  30. // this code is required to serve as the template code for other language
  31. // stacks. Thus, this code only uses a uniform distribution of doubles [0,1)
  32. // and then provides the distribution functions itself.
  33. class RandomDistInterface {
  34. public:
  35. RandomDistInterface() {}
  36. virtual ~RandomDistInterface() = 0;
  37. // Argument to transform is a uniform double in the range [0,1)
  38. virtual double transform(double uni) const = 0;
  39. };
  40. inline RandomDistInterface::~RandomDistInterface() {}
  41. // ExpDist implements an exponential distribution, which is the
  42. // interarrival distribution for a Poisson process. The parameter
  43. // lambda is the mean rate of arrivals. This is the
  44. // most useful distribution since it is actually additive and
  45. // memoryless. It is a good representation of activity coming in from
  46. // independent identical stationary sources. For more information,
  47. // see http://en.wikipedia.org/wiki/Exponential_distribution
  48. class ExpDist final : public RandomDistInterface {
  49. public:
  50. explicit ExpDist(double lambda) : lambda_recip_(1.0 / lambda) {}
  51. ~ExpDist() override {}
  52. double transform(double uni) const override {
  53. // Note: Use 1.0-uni above to avoid NaN if uni is 0
  54. return lambda_recip_ * (-log(1.0 - uni));
  55. }
  56. private:
  57. double lambda_recip_;
  58. };
  59. // A class library for generating pseudo-random interarrival times
  60. // in an efficient re-entrant way. The random table is built at construction
  61. // time, and each call must include the thread id of the invoker
  62. class InterarrivalTimer {
  63. public:
  64. InterarrivalTimer() {}
  65. void init(const RandomDistInterface& r, int threads, int entries = 1000000) {
  66. std::random_device devrand;
  67. std::mt19937_64 generator(devrand());
  68. std::uniform_real_distribution<double> rando(0, 1);
  69. for (int i = 0; i < entries; i++) {
  70. random_table_.push_back(
  71. static_cast<int64_t>(1e9 * r.transform(rando(generator))));
  72. }
  73. // Now set up the thread positions
  74. for (int i = 0; i < threads; i++) {
  75. thread_posns_.push_back(random_table_.begin() + (entries * i) / threads);
  76. }
  77. }
  78. virtual ~InterarrivalTimer(){};
  79. int64_t next(int thread_num) {
  80. auto ret = *(thread_posns_[thread_num]++);
  81. if (thread_posns_[thread_num] == random_table_.end()) {
  82. thread_posns_[thread_num] = random_table_.begin();
  83. }
  84. return ret;
  85. }
  86. private:
  87. typedef std::vector<int64_t> time_table;
  88. std::vector<time_table::const_iterator> thread_posns_;
  89. time_table random_table_;
  90. };
  91. } // namespace testing
  92. } // namespace grpc
  93. #endif