Is this library method CPU-bound or I/O-bound?
On trails:CSASYNCstep 7/11
A signature does not say whether a method is CPU-bound or I/O-bound (see I/O-bound or CPU-boundI/O-bound or CPU-bound?Async helps most when the work is waiting, and CPU-heavy work needs Task.Run.Opens in a new tab).
- What it touches. A
Stream,HttpClient,SqlConnection,File.*or socket means I/O. Transforming bytes already in memory (parsing, decoding, resizing, compressing) means CPU. This settles most cases. - The
Asyncsuffix or aTaskreturn proves nothing. Fake async methods callTask.Run(() => Sync())or wrap a result inTask.FromResult, and still use a pool thread. - The source, if open: look for
Stream.ReadAsync, sockets orHttpClient(I/O), or loops and math with no I/O (CPU). - Run it and watch. A core near 100% for the duration means CPU-bound. Near-idle CPU while the call runs means I/O-bound.
dotnet-countersworks for closed-source libraries. - A profiler. A
dotnet-traceshows a thread either executing code (CPU) or blocked in a kernel wait or I/O completion (I/O). - A sync-only method.
RenderPage(data)with noRenderPageAsynchints at CPU-bound work, since authors usually offer async for I/O. It is not proof.
Example
In a PDF library, a page-loading method with a real LoadPageAsync that awaits streamStreamsReading and writing data as a flow of bytes, a chunk at a time.Opens in a new tab reads is I/O, so it suits Task.WhenAll or channels. Page rendering is CPU-bound (rasterization, font shaping), even if wrapped in Task.Run, so it needs explicit parallelism (see the load-then-render pipelineLoad everything then render, or stream through a channelTwo shapes for a job that loads data (I/O) and renders it (CPU).Opens in a new tab).