artdaq  v3_12_02
RandomDelayFilter_module.cc
1 // Class: RandomDelayFilter
3 // Module Type: filter
4 // File: RandomDelayFilter_module.cc
5 //
6 // Generated at Fri Mar 4 10:45:30 2016 by Eric Flumerfelt using artmod
7 // from cetpkgsupport v1_09_00.
9 
10 #include "TRACE/tracemf.h"
11 #define TRACE_NAME "RandomDelayFilter"
12 
13 #include "artdaq-core/Utilities/TimeUtils.hh"
14 
15 #include "art/Framework/Core/EDFilter.h"
16 #include "art/Framework/Core/ModuleMacros.h"
17 #include "art/Framework/Principal/Event.h"
18 #include "art/Framework/Principal/Handle.h"
19 #include "art/Framework/Principal/Run.h"
20 #include "art/Framework/Principal/SubRun.h"
21 #include "canvas/Utilities/InputTag.h"
22 #include "fhiclcpp/ParameterSet.h"
23 
24 #include <chrono>
25 #include <memory>
26 #include <random>
27 
28 namespace artdaq {
29 class RandomDelayFilter;
30 }
31 
39 class artdaq::RandomDelayFilter : public art::EDFilter
40 {
41 public:
56  explicit RandomDelayFilter(fhicl::ParameterSet const& p);
57 
58  ~RandomDelayFilter() override = default;
59 
63  RandomDelayFilter(RandomDelayFilter const&) = delete;
64 
69 
75 
81 
91  bool filter(art::Event& e) override;
92 
93 private:
94  // Random Delay Parameters (min/max for uniform, mean/sigma for normal)
95  double min_ms_;
96  double max_ms_;
97  double mean_ms_;
98  double sigma_ms_;
99 
100  int pass_factor_;
101  double load_factor_;
102 
103  // Random Engine Setup
104  std::mt19937 engine_;
105  std::unique_ptr<std::uniform_real_distribution<double>> uniform_distn_;
106  std::unique_ptr<std::normal_distribution<double>> normal_distn_;
107  std::unique_ptr<std::exponential_distribution<double>> exponential_distn_;
108  std::unique_ptr<std::uniform_int_distribution<int>> pass_distn_;
109 
110  enum class DistType
111  {
112  Fixed,
113  Uniform,
114  Normal,
115  Exponential
116  };
117  DistType distribution_type_;
118 };
119 
120 artdaq::RandomDelayFilter::RandomDelayFilter(fhicl::ParameterSet const& p)
121  : art::EDFilter(p)
122  , min_ms_(p.get<double>("minimum_delay_ms", 0))
123  , max_ms_(p.get<double>("maximum_delay_ms", 1000))
124  , mean_ms_(p.get<double>("mean_delay_ms", 500))
125  , sigma_ms_(p.get<double>("sigma_delay_ms", 100))
126  , pass_factor_(p.get<int>("pass_filter_percentage", 100))
127  , load_factor_(p.get<double>("cpu_load_ratio", 0.5))
128  , engine_(p.get<int64_t>("random_seed", time(nullptr)))
129  , pass_distn_(new std::uniform_int_distribution<int>(0, 100))
130 {
131  // Set limits on parameters
132  if (pass_factor_ > 100)
133  {
134  pass_factor_ = 100;
135  }
136  if (pass_factor_ < 0)
137  {
138  pass_factor_ = 0;
139  }
140  if (load_factor_ < 0.0)
141  {
142  load_factor_ = 0.0;
143  }
144  if (load_factor_ > 1.0)
145  {
146  load_factor_ = 1.0;
147  }
148 
149  if (min_ms_ < 0)
150  {
151  min_ms_ = 0;
152  }
153  if (min_ms_ > max_ms_)
154  {
155  max_ms_ = min_ms_;
156  }
157  if (mean_ms_ < 0)
158  {
159  mean_ms_ = 0;
160  }
161  if (sigma_ms_ < 0)
162  {
163  sigma_ms_ = 0;
164  }
165 
166  auto type = p.get<std::string>("distribution_type", "Uniform");
167  assert(!type.empty());
168  switch (type[0])
169  {
170  case 'n':
171  case 'N':
172  TLOG(TLVL_INFO) << "Generating delay times using Normal distribution with mean " << mean_ms_ << " ms, std. dev. " << sigma_ms_ << " ms, min " << min_ms_ << " ms and max " << max_ms_ << "ms.";
173  distribution_type_ = DistType::Normal;
174  if (mean_ms_ < min_ms_)
175  {
176  TLOG(TLVL_WARNING) << "Mean is smaller than min, setting to min";
177  mean_ms_ = min_ms_;
178  }
179  mean_ms_ -= min_ms_; // When we sample the distribution, we offset by min_ms_
180  normal_distn_ = std::make_unique<std::normal_distribution<double>>(mean_ms_, sigma_ms_);
181  break;
182  case 'e':
183  case 'E':
184  TLOG(TLVL_INFO) << "Generating delay times using Exponential distribution with mean " << mean_ms_ << " ms, min " << min_ms_ << " ms and max " << max_ms_ << " ms.";
185  distribution_type_ = DistType::Exponential;
186  if (mean_ms_ < min_ms_)
187  {
188  TLOG(TLVL_WARNING) << "Mean is smaller than min, setting to min";
189  mean_ms_ = min_ms_;
190  }
191  mean_ms_ -= min_ms_; // When we sample the distribution, we offset by min_ms_
192  if (mean_ms_ == 0)
193  {
194  mean_ms_ = 1;
195  }
196  exponential_distn_ = std::make_unique<std::exponential_distribution<double>>(1 / mean_ms_);
197  break;
198  case 'U':
199  case 'u':
200  TLOG(TLVL_INFO) << "Generating delay times using Uniform distribution with min " << min_ms_ << " ms and max " << max_ms_ << " ms.";
201  distribution_type_ = DistType::Uniform;
202  uniform_distn_ = std::make_unique<std::uniform_real_distribution<double>>(min_ms_, max_ms_);
203  break;
204  case 'f':
205  case 'F':
206  default:
207  TLOG(TLVL_INFO) << "Delay time set to " << min_ms_ << " ms.";
208  distribution_type_ = DistType::Fixed;
209  break;
210  }
211 }
212 
214 {
215  double delay = min_ms_;
216  do
217  {
218  switch (distribution_type_)
219  {
220  case DistType::Normal:
221  delay += (*normal_distn_)(engine_);
222  break;
223  case DistType::Exponential:
224  delay += (*exponential_distn_)(engine_);
225  break;
226  case DistType::Uniform:
227  delay = (*uniform_distn_)(engine_);
228  break;
229  case DistType::Fixed:
230  break;
231  }
232  } while (delay > max_ms_ && delay < min_ms_);
233  TLOG(TLVL_DEBUG) << "Simulating processing of event " << e.event() << " by delaying " << delay << "ms.";
234 
235  usleep(static_cast<unsigned>(1000 * (1 - load_factor_) * delay));
236 
237  auto i = 0;
238  auto now = std::chrono::steady_clock::now();
239  while (TimeUtils::GetElapsedTimeMilliseconds(now) < static_cast<size_t>(delay * load_factor_))
240  {
241  i = i + 1 % std::numeric_limits<int>::max();
242  }
243 
244  return (*pass_distn_)(engine_) < pass_factor_;
245 }
246 
247 DEFINE_ART_MODULE(artdaq::RandomDelayFilter) // NOLINT(performance-unnecessary-value-param)
RandomDelayFilter(fhicl::ParameterSet const &p)
RandomDelayFilter Constructor.
bool filter(art::Event &e) override
Filter is a required override of art::EDFilter, and is called for each event.
A filter which delays for a random amount of time, then drops a random fraction of events...
RandomDelayFilter & operator=(RandomDelayFilter const &)=delete
Copy Assignment operator is deleted.