boost::asio::d eadline_timer 1ms 滞后一段时间

boost::asio::deadline_timer 1ms lags after some time

本文关键字:1ms 滞后 一段时间 timer eadline asio boost      更新时间:2023-10-16

我使用 boost::asio::d eadline_timer 实现了一个计时器。 我使用 expires_from_now(boost::p osix_time::milliseconds(1)) 运行计时器

我数了数,它在 10 秒内触发的频率(在 Windows 下)。我期待10 000次。

结果如下: 在一台PC计数器上非常准确 - 每10秒10 000次。 在其他PC上,计数器在7000和8500之间随机变化。 问题:一段时间后,计数减少到每 600 秒 800-10 次。

当我仍然使用间隔为 10 毫秒的计时器时,我无法找出将超时增加到 ~15 毫秒的原因是什么。

我在电源管理中检查了处理器电源设置 - 最低性能为 100% .Windows 中是否有任何其他设置可能会影响不同电脑上的结果? 为什么在运行程序一段时间后会发生这种情况?

如果您依赖于以最佳精度满足截止日期,而不是等待"x"毫秒,只需绝对说明它们:

住在科里鲁

#include <boost/asio.hpp>
#include <boost/asio/high_resolution_timer.hpp>
#include <iostream>
namespace ba = boost::asio;
using namespace std::chrono_literals;
int main() {
ba::io_context io;
using C = ba::high_resolution_timer::clock_type;
ba::high_resolution_timer t(io);
auto next_wakeup = [&t, interval = 10ms] {
t.expires_at(C::now() + interval);
t.wait();
};
auto until = C::now() + 5s;
int count = 0;
do count += 1;
while (next_wakeup(), C::now() <= until);
std::cout << "Timer triggered " << count << " times in 5sn";
}

在我的系统上,它报告 497,因此您可以看到循环开销足以总共错过几个截止日期。如果降低频率,这一点会变得更加重要。

替代方法

当然,你可以使事情多线程化,并在线程之间分配计时器事件,这样就会减少错过的事件。或者你可以看看Boost Thread中的实验性调度程序。

如果更改设计权衡以最大程度地减少遗漏的事件,代价是(可能)具有更高的噪声频率/间隔:

请注意每次如何小心地从起点计算下一个事件,以便可以指定INTERVAL,其精度在时钟time_point中无法表示:

auto constexpr INTERVAL = 1.0/3ms;

表示法。否则可能会累积舍入误差。

住在科里鲁

#include <boost/asio.hpp>
#include <boost/asio/high_resolution_timer.hpp>
#include <boost/thread.hpp>
using namespace std::chrono_literals;
namespace /*static*/ {
auto constexpr INTERVAL = 1ms;
auto constexpr DURATION = 5s;
std::atomic_int count {0};
void on_timer_event() { ++count; }
}
namespace ba = boost::asio;
using Timer = ba::high_resolution_timer;
using C = Timer::clock_type;
template <typename Interval>
static void timer_chain(Timer& t, C::time_point start_point, Interval ival, int n = 0) {
t.expires_at(start_point + std::chrono::duration_cast<C::duration>(n * ival));
t.async_wait([=,&t](auto ec) {
if (!ec) {
on_timer_event();
timer_chain(t, start_point, ival, n+1);
}
});
}
#include <iostream>
int main() {
ba::io_context io;
boost::thread_group tg;
std::list<Timer> timers;
auto const slices = 10;
auto const start_point = C::now();
auto group_interval = INTERVAL * slices;
for (auto slice = 0; slice<slices; ++slice)
timer_chain(timers.emplace_back(io), start_point + slice*INTERVAL, group_interval);
for (unsigned i = 0; i < std::thread::hardware_concurrency(); ++i)
tg.create_thread([&io] { io.run_for(DURATION); });
std::cout << "Running on " << tg.size() << " threads...n";
tg.join_all();
std::cout << "Event triggered " << count << " times in " << (C::now() - start_point)/1ms << "msn";
}

这打印

Running on 1 threads...
Event triggered 5002 times in 5001ms

或者,在我的系统上:

Running on 8 threads...
Event triggered 5002 times in 5001ms