1

Suppose we have an app running multiple network clients which make a loop: send a request, then pauses for specified time, and again.

Example (not all the code):

#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_;
}

Question is: when running many clients (like 100 or so) the deadline_timer actually waits for several seconds, not near 1000 ms, but about 9000 ms and even more.

How to avoid this or how to rewrite program so that each client will wait for given wait interval plus-minus some little difference?

vladon
  • 8,158
  • 2
  • 47
  • 91
  • @RichardHodges Thank you, Richard, but question is not about how to implement async client and server. Please read the question BEFORE answering. – vladon Dec 02 '15 at 10:21
  • You're welcome, but you won't get anywhere with timeouts without an async solution;) – Richard Hodges Dec 02 '15 at 10:44
  • @RichardHodges My code is exactly based on those examples. It (timers) works ok when number of clients is low. But they wait too long when number of clients is big (100+). Have you an answer how to implement timeouts for such a number of clients? Or can you point the particular example? – vladon Dec 02 '15 at 11:01
  • ok I guess the question here is "where are the delays occurring?". The handlers for timers will be executed through the io_service queue. If that queue is loaded, the timer events will have to wait their turn. could it be that the work being done by the clients is not yielding often enough? Without metrics its difficult to speculate... – Richard Hodges Dec 02 '15 at 11:28

1 Answers1

0

simply do not wait for the timer to expire, but pass a handler to be called when the timer expires. In an ASIO application, the only blocking call should be to io_service::run().

Torsten Robitzki
  • 3,041
  • 1
  • 21
  • 35
  • If I change it to `timer.async_wait` with handler, the result is the same. – vladon Dec 02 '15 at 10:04
  • I changed code in question. – vladon Dec 02 '15 at 10:07
  • Are you sure, that your server is not suffering from too much CPU load? – Torsten Robitzki Dec 02 '15 at 10:11
  • Sorry, but your server is busy looping over all connections. Just don't do that. Handle everything asynchronously and spawn the required amount of threads to just call `io_service_.run()`. – Torsten Robitzki Dec 02 '15 at 10:13
  • Sorry, when simplifying code I forgot it. Updated to actually used (with spawn and yield). CPU load is about 2-4%. – vladon Dec 02 '15 at 10:18
  • I would think that anywhere in your code, the CPU is blocking on a synchronous function call. You can do a simple test: Start your application in a debugger. Then interrupt the program and inspect all threads and look for function, where you know that they are synchronous (database, sleep(), etc.). Good Luck! ;-) – Torsten Robitzki Dec 02 '15 at 10:31