With official C++20 inclusion of coroutines it gets important to identify synchronous code usage inside of coroutines. Volunteer preemption of a system thread in asynchronous code (e.g. in
coroutines/fibers/green threads) is a bug that prevents the current thread from executing other coroutines/etc. and negatively affects overall process performance.
I've tried to address it in a series of clang-tidy checks that
try to find such synchronous code based on blacklists from
POSIX/C++ std/C11/Boost/Linux syscalls. Basically, one should enable concurrency-*
checks for the strictest mode. It finds usages of synchronous primitives (e.g. std::mutex), fs access (e.g. open(3)), implicit system threads creation (e.g. via std::execution::par). In some cases one may want to relax the check, e.g.:
- if new threads creation is not an issue, I don't force coroutine-only code, just don't want to block coroutine threads => disable concurrency-async-no-new-threads
- if I have no means to delegate fs access to a thread pool and don't want to use aio, so I have to make synchronous fs access from coroutines => disable concurrency-async-fs
Nathan James in a review (https://reviews.llvm.org/D94621#2497859) questions whether such check based on functions/types blacklist worth implementing. I think it does as every coroutine/fiber-based C++ program may suffer from the same problem - you may not use a lot of std stuff unless you're OK with ineffective code, so having such "do not use part of std/boost" checks is handy.
concurrency-async-blocking: ⚙ D93940 [clang-tidy] Add a check for blocking types and functions.
concurrency-async-fs: ⚙ D94621 [clang-tidy] add concurrency-async-fs
concurrency-async-no-new-threads: ⚙ D94622 [clang-tidy] add concurrency-async-no-new-threads
The patch series are based on a much more simple check used in Yandex.Taxi. I think it worth something to the community, so I've separated a big list of functions/types apart to address e.g. environments without fs threadpool, and added possibility to extend the types/functions lists via option.
I'd be happy to hear any comments how the checks can be improved, or maybe organized in some other way, or whether they confront any implicit clang-tidy policy.