Boost logo

Boost Users :

Subject: Re: [Boost-users] [asio] Using io_service for synchronous tcp accept + custom tasks
From: Gavin Lambert (gavinl_at_[hidden])
Date: 2015-02-04 18:59:21

On 4/02/2015 20:38, Aaron Levy wrote:
> 04.02.2015, 06:22, "Gavin Lambert" <gavinl_at_[hidden]>:
>> Also, I could be wrong about this, but I think if you eg. perform a
>> blocking read inside your sock job it will tie up a whole thread for the
>> duration, which means that you will quickly run out if you get multiple
>> connections. Using async code should avoid this.
> Consider an alternative to my example while still using sync I/O.
> io_service svc;
> endpoint ep(ip::tcp::v4(), port);
> acceptor acceptor(svc, ep);
> boost::thread_group group;
> while (true) {
> shared_ptr<socket> sock(new socket(svc));
> acceptor.accept(*sock);
> group.create_thread([sock]() { /* do some processing */ });
> }
> group.join_all(); // we never reach here
> The problem with the first example would manifest itself with
> increasing rate of connections - connections would take longer to be
> accepted and be ready for read / write. With this one, connections
> would not remain hung up for too long, but subsequent I/O could
> because there could be too many threads vying for the processors. I'm
> wondering which one would be preferable.

Using a thread per connection is a server antipattern. You can usually
get away with it for a surprisingly large number of connections, but
it's still highly vulnerable to a DDoS (either as an actual attack or
just from becoming too popular).

> Are there any specific advantages of sync I/O over async I/O other
> than simple code?

No, the only advantage of sync I/O is that it's easier for humans to
follow. (Well, that's not strictly true; if you do bind a single thread
per connection then you can make use of TLS, and a few other esoteric
bits like that.)

Async code in general performs better (if written properly, which can be
trickier than sync code) because threads only wait for work when there
is no work to do, not blocking because one particular connection has
nothing to do. So you need less threads overall and there are less
context switches required when multiple items of work are ready. But
the code is a bit more disjointed (although lambdas can help with this).

Coroutines are a good compromise between the two -- they read almost
like synchronous code but have performance closer to async code.

Boost-users list run by williamkempf at, kalb at, bjorn.karlsson at, gregod at, wekempf at