【问题标题】:Using many boost::asio::deadline_timer [duplicate]使用许多 boost::asio::deadline_timer [重复]
【发布时间】:2015-12-02 09:52:20
【问题描述】:

假设我们有一个运行多个网络客户端的应用程序,它们形成一个循环:发送一个请求,然后暂停指定时间,然后再一次。

示例(并非所有代码):

#define WAIT_INTERVAL 1000

class client()
{
public:
    explicit client(boost::asio::io_service & io_service)
        : io_service_(io_service) 
    { 
        working_ = true; 
    };

    run(boost::asio::yield_context t_yield) 
    {
        while (working_) {
            // async wait
            boost::asio::deadline_timer timer(io_service_, boost::posix::milliseconds(WAIT_INTERVAL));

            timer.async_wait(t_yield);

            do_work();
        }
    };

private:
    void do_work()
    {
        // make work
    }

    bool working_{ false };
    boost::asio::io_service & io_service_;
}

class app()
{
public:
    // code omitted

    prepare(size_t number_of_clients)
    {
        clients_.reserve(number_of_clients);

        for (size_t i = 0; i < number_of_clients; ++i) 
        {
            clients_.emplace_back(io_service_);
        }
    }

    run()
    {
        for (auto & client : clients_) 
        {
            boost::asio::spawn(io_service_, [&client](boost::asio::yield_context t_yield)
            {
                client.run(t_yield);
            });
        }
    }

private:
    boost::asio::io_service io_service_;
    std::vector<client> clients_;
}

问题是:当运行许多客户端(比如 100 个左右)时,deadline_timer 实际上会等待几秒钟,不是接近 1000 毫秒,而是大约 9000 毫秒甚至更多。

如何避免这种情况或如何重写程序,以便每个客户端将等待给定的等待间隔加减一些小的差异?

【问题讨论】:

  • @RichardHodges 谢谢你,Richard,但问题不在于如何实现异步客户端和服务器。请在回答之前阅读问题。
  • 不客气,但如果没有异步解决方案,您将无法在超时的情况下取得任何进展;)
  • @RichardHodges 我的代码正是基于这些示例。当客户端数量较少时,它(计时器)可以正常工作。但是当客户数量很大(100+)时,他们等待的时间太长了。您是否知道如何为如此多的客户实施超时?或者你能指出具体的例子吗?
  • 好的,我想这里的问题是“延迟发生在哪里?”。计时器的处理程序将通过 io_service 队列执行。如果加载了该队列,则计时器事件将不得不等待轮到它们。会不会是客户所做的工作没有得到足够的回报?没有指标就很难推测...

标签: c++ multithreading timer boost-asio


【解决方案1】:

只是不要等待定时器到期,而是传递一个处理程序以在定时器到期时调用。在 ASIO 应用程序中,唯一的阻塞调用应该是io_service::run()

【讨论】:

  • 如果我用handler把它改成timer.async_wait,结果是一样的。
  • 我更改了有问题的代码。
  • 您确定您的服务器没有承受过多的 CPU 负载吗?
  • 抱歉,您的服务器正忙于循环所有连接。只是不要那样做。异步处理所有内容并生成所需数量的线程,只需调用io_service_.run()
  • 抱歉,我在简化代码时忘记了。更新为实际使用(使用 spawn 和 yield)。 CPU 负载约为 2-4%。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多