[ASIO] Using boost::asio::thread_pool with sockets without boost::asio::io_context

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

[ASIO] Using boost::asio::thread_pool with sockets without boost::asio::io_context

Boost - Users mailing list
Hello,

One strategy to load-balance I/O processing across multiple
threads is to use a single io_context object for multiplexing and
to call io_context::run from all threads in the thread pool. This
can be set up by, for example, defining a type which holds a
vector of threads, all of which are calling io_context::run. My
first question is: is this approach of calling io_context::run
from several threads somewhat equivalent to using
boost::asio::thread_pool as the default execution context and
not (explicitly, at least) creating a boost::asio::io_context
object at all?

Somewhat more specifically, is it safe to define TCP
sockets/acceptors/etc. with execution contexts set to a
boost::asio::thread_pool instead of io_context, and will that
work as expected (i.e., as a single io_context object scheduling
tasks out to several threads calling io_context::run would)?

-Ani
_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [ASIO] Using boost::asio::thread_pool with sockets without boost::asio::io_context

Boost - Users mailing list


On Thu, 9 Jul 2020 at 16:02, Aniruddh Agarwal via Boost-users <[hidden email]> wrote:
Hello,

One strategy to load-balance I/O processing across multiple
threads is to use a single io_context object for multiplexing and
to call io_context::run from all threads in the thread pool. This
can be set up by, for example, defining a type which holds a
vector of threads, all of which are calling io_context::run. My
first question is: is this approach of calling io_context::run
from several threads somewhat equivalent to using
boost::asio::thread_pool as the default execution context and
not (explicitly, at least) creating a boost::asio::io_context
object at all?

It's not equivalent because in the case of one thread per io_context, the completion handler of asynchronous operations will always be invoked on a known thread. Therefore concurrency protection is not a concern.

If you use the executor of a thread_pool, there is no guarantee which thread will invoke the completion handler, and no guarantee that two completion handlers will not touch the same user object. This argues for the use of asio::strand<asio::thread_pool::executor_type> as the executor to be associated with the completion handler (or set as the default executor of related io objects).

 

Somewhat more specifically, is it safe to define TCP
sockets/acceptors/etc. with execution contexts set to a
boost::asio::thread_pool instead of io_context, and will that
work as expected (i.e., as a single io_context object scheduling
tasks out to several threads calling io_context::run would)?

It will work. You will need to add concurrency protection, and it will be less efficient. From your line of questioning I don't think it will work as you are expecting or hoping.

Is there a use case or is this a question out of curiosity?

 

-Ani
_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users


--
Richard Hodges
office: +442032898513
home: +376841522
mobile: +376380212


_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [ASIO] Using boost::asio::thread_pool with sockets without boost::asio::io_context

Boost - Users mailing list
On Jul 9, 2020, at 10:49 AM, Richard Hodges via Boost-users <[hidden email]> wrote:
> It's not equivalent because in the case of one thread per io_context, the completion handler of asynchronous operations will always be invoked on a known thread. Therefore concurrency protection is not a concern.
>
> If you use the executor of a thread_pool, there is no guarantee which thread will invoke the completion handler, and no guarantee that two completion handlers will not touch the same user object. This argues for the use of asio::strand<asio::thread_pool::executor_type> as the executor to be associated with the completion handler (or set as the default executor of related io objects).

It seems that my original email was a bit misleading and implied that I was comparing (many threads, many asio::io_context objects) with asio::thread_pool. In fact, I’m trying to compare (many threads, one asio::io_context object) with asio::thread_pool. From what you’ve said above, it looks like (many threads, one asio::io_context object) and asio::thread_pool are logically equivalent.

Can you speak to any performance differences between these (or point to reference material which touches on this)?

> Is there a use case or is this a question out of curiosity?

Mostly out of curiosity. I’ve found myself repeatedly writing code where a single asio::io_context is dishing out tasks to many threads, and am wondering if asio::thread_pool is a drop-in replacement for manually setting up a thread pool and calling asio::io_context::run from each thread.

 -Ani

_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [ASIO] Using boost::asio::thread_pool with sockets without boost::asio::io_context

Boost - Users mailing list


On Thu, 9 Jul 2020 at 18:01, Aniruddh Agarwal via Boost-users <[hidden email]> wrote:
On Jul 9, 2020, at 10:49 AM, Richard Hodges via Boost-users <[hidden email]> wrote:
> It's not equivalent because in the case of one thread per io_context, the completion handler of asynchronous operations will always be invoked on a known thread. Therefore concurrency protection is not a concern.
>
> If you use the executor of a thread_pool, there is no guarantee which thread will invoke the completion handler, and no guarantee that two completion handlers will not touch the same user object. This argues for the use of asio::strand<asio::thread_pool::executor_type> as the executor to be associated with the completion handler (or set as the default executor of related io objects).

It seems that my original email was a bit misleading and implied that I was comparing (many threads, many asio::io_context objects) with asio::thread_pool. In fact, I’m trying to compare (many threads, one asio::io_context object) with asio::thread_pool. From what you’ve said above, it looks like (many threads, one asio::io_context object) and asio::thread_pool are logically equivalent.

From the soon to be released boost 1.74 docs, the executor_type of io_context and thread_pool are the same type: typedef basic_executor_type< std::allocator< void >, 0 > executor_type; , so it seems that it is intended that they will have the same behaviour.
 

Can you speak to any performance differences between these (or point to reference material which touches on this)?

I cannot point you to material offhand, but you have reminded me that I read this *somewhere*. I seem to remember something about there needing to be something that's calling epoll/select/pselect in a loop. But now you've got me wondering if I am mistaken. Of course if your worker thread is just making a blocking call to run(), that's where the io loop will happen. Your handlers will be executed within the context of the io_context::run which will happen on a thread associated with the thread_pool.


> Is there a use case or is this a question out of curiosity?

Mostly out of curiosity. I’ve found myself repeatedly writing code where a single asio::io_context is dishing out tasks to many threads, and am wondering if asio::thread_pool is a drop-in replacement for manually setting up a thread pool and calling asio::io_context::run from each thread.

I suppose this could save you a few lines of code.

 

 -Ani

_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users


--
Richard Hodges
office: +442032898513
home: +376841522
mobile: +376380212


_______________________________________________
Boost-users mailing list
[hidden email]
https://lists.boost.org/mailman/listinfo.cgi/boost-users