19 #include <ripple/beast/asio/io_latency_probe.h>
20 #include <ripple/beast/unit_test.h>
22 #include <ripple/beast/test/yield_to.hpp>
24 #include <boost/asio/basic_waitable_timer.hpp>
25 #include <boost/asio/deadline_timer.hpp>
26 #include <boost/asio/io_service.hpp>
36 using namespace std::chrono_literals;
39 public beast::test::enable_yield_to
42 boost::asio::basic_waitable_timer<std::chrono::steady_clock>;
44 #ifdef RIPPLED_RUNNING_IN_CI
55 struct measure_asio_timers
57 using duration =
typename Clock::duration;
58 using rep =
typename MeasureClock::duration::rep;
62 measure_asio_timers(duration interval = 100ms,
size_t num_samples = 50)
65 boost::asio::io_service ios;
68 boost::asio::basic_waitable_timer<Clock> timer{ios};
69 elapsed_times_.
reserve(num_samples);
74 boost::system::error_code wait_err;
78 auto const start{MeasureClock::now()};
80 timer.expires_after(interval);
81 timer.async_wait([&](boost::system::error_code
const& ec) {
84 auto const end{MeasureClock::now()};
90 cv.
wait(mainlock, [&done] {
return done; });
95 boost::asio::detail::throw_error(wait_err,
"wait");
103 for (
auto const& v : elapsed_times_)
105 sum +=
static_cast<double>(
106 std::chrono::duration_cast<D>(v).count());
108 return sum / elapsed_times_.size();
115 return std::chrono::duration_cast<D>(
117 elapsed_times_.
begin(), elapsed_times_.
end()))
125 return std::chrono::duration_cast<D>(
127 elapsed_times_.
begin(), elapsed_times_.
end()))
140 boost::asio::io_service& ios)
141 : probe_(interval, ios)
158 operator()(std::chrono::steady_clock::duration
const& elapsed)
167 testcase <<
"sample one";
168 boost::system::error_code ec;
171 MyTimer timer{get_io_service(), 1s};
172 timer.async_wait(yield[ec]);
173 if (!BEAST_EXPECTS(!ec, ec.message()))
175 BEAST_EXPECT(io_probe.durations_.size() == 1);
176 io_probe.probe_.cancel_async();
182 testcase <<
"sample ongoing";
183 boost::system::error_code ec;
185 auto interval = 99ms;
186 auto probe_duration = 1s;
188 size_t expected_probe_count_max = (probe_duration / interval);
189 size_t expected_probe_count_min = expected_probe_count_max;
190 #ifdef RIPPLED_RUNNING_IN_CI
193 measure_asio_timers<steady_clock> tt{interval};
198 expected_probe_count_min =
200 duration_cast<milliseconds>(probe_duration).count()) /
205 MyTimer timer{get_io_service(), probe_duration};
206 timer.async_wait(yield[ec]);
207 if (!BEAST_EXPECTS(!ec, ec.message()))
209 auto probes_seen = io_probe.durations_.size();
211 probes_seen >= (expected_probe_count_min - 1) &&
212 probes_seen <= (expected_probe_count_max + 1),
214 io_probe.probe_.cancel_async();
217 timer.expires_from_now(1s);
218 timer.async_wait(yield[ec]);
224 testcase <<
"canceled";
227 except<std::logic_error>([&io_probe]() { io_probe.start_one(); });
228 except<std::logic_error>([&io_probe]() { io_probe.start(); });
235 yield_to([&](boost::asio::yield_context& yield) {
236 testSampleOne(yield);
237 testSampleOngoing(yield);