Repository: tokio-rs/tokio
File: tokio-util/src/io/sync_bridge.rs (Rust)

Code before:
///
/// When hashing data, using `SyncIoBridge` can lead to suboptimal performance and might not fully leverage the async capabilities of the system.
/// Instead, consider reading the data into memory and then hashing it, or processing the data in chunks.
///
/// ```rust, no_run
/// let mut data = Vec::new();
/// reader.read_to_end(&mut data).await?;
/// let hash = blake3::hash(&data);
/// ```
///
/// Or, for more complex cases:
///
/// ```rust, no_run
/// let mut data = vec![0; 64 * 1024];
/// loop {
///     let len = reader.read(&mut data).await?;
///     if len == 0 { break; }
///     hasher.update(&data[..len]);
/// }
/// let hash = hasher.finalize();
/// ```
///
/// ## Example 2: Compressing Data
///
/// When compressing data, avoid using `SyncIoBridge`` with non-async compression libraries, as it may lead to inefficient and blocking code.
/// Instead, use `async-compression`, which is designed to work with asynchronous data streams.
///
/// ```rust, no_run
/// use async_compression::tokio::write::GzipEncoder;
///
/// let mut encoder = GzipEncoder::new(writer);
/// tokio::io::copy(&mut reader, &mut encoder).await?;
/// ```
///
/// ## Example 3: Parsing `JSON`
///
/// When parsing `JSON` data, avoid using `SyncIoBridge` with `serde_json::from_reader` as it may cause blocking operations.
/// Instead, read the data into a `Vec<u8>` and parse it using `serde_json::from_slice`.
///
/// ```rust, no_run
/// let mut data = Vec::new();
/// reader.read_to_end(&mut data).await?;
/// let value: MyStruct = serde_json::from_slice(&data)?;
/// ```
///
/// ## Correct Usage of `SyncIoBridge` inside `spawn_blocking`
///
/// `SyncIoBridge` is mainly useful when you need to interface with synchronous libraries from an asynchronous context.
/// Here is how you can do it correctly:
///
/// ```rust, no_run

Review comment (suggestion):
I'd prefer not to recommend a specific library in the tokio documentation, because it might not work for all use-cases. I might say
```suggestion
/// Instead, use an async compression library, such as the `async-compression` crate, which is designed to work with asynchronous data streams.
```

Also, if we are going to recommend this crate specifically, we should probably link to its documentation.

Code after:
/// might not fully leverage the async capabilities of the system.
///
/// ### Why It Matters:
///
/// `SyncIoBridge` allows you to use asynchronous I/O operations in an synchronous
/// context by blocking the current thread. However, this can be inefficient because:
/// - **Inefficient Resource Usage**: `SyncIoBridge` takes up an entire OS thread,
///   which is inefficient compared to asynchronous code that can multiplex many
///   tasks on a single thread.
/// - **Thread Pool Saturation**: Excessive use of `SyncIoBridge` can exhaust the
///   async runtime's thread pool, reducing the number of threads available for
///   other tasks and impacting overall performance.
/// - **Missed Concurrency Benefits**: By using synchronous operations with
///   `SyncIoBridge`, you lose the ability to interleave tasks efficiently,
///   which is a key advantage of asynchronous programming.
///
/// ## Example 1: Hashing Data
///
/// The use of `SyncIoBridge` is unnecessary when hashing data. Instead, you can
/// process the data asynchronously by reading it into memory, which avoids blocking
/// the async runtime.
///
/// There are two strategies for avoiding `SyncIoBridge` when hashing data. When
/// the data fits into memory, the easiest is to read the data into a `Vec<u8>`
/// and hash it:
///
/// Explanation: This example demonstrates how to asynchronously read data from a
/// reader into memory and hash it using a synchronous hashing function. The
/// `SyncIoBridge` is avoided, ensuring that the async runtime is not blocked.
/// ```rust
/// use tokio::io::AsyncReadExt;
/// use tokio::io::AsyncRead;
/// use std::io::Cursor;
/// # mod blake3 { pub fn hash(_: &[u8]) {} }
///
/// async fn hash_contents(mut reader: impl AsyncRead + Unpin) -> Result<(), std::io::Error> {
///    // Read all data from the reader into a Vec<u8>.
///    let mut data = Vec::new();
///    reader.read_to_end(&mut data).await?;
///
///    // Hash the data using the blake3 hashing function.
///    let hash = blake3::hash(&data);
///
///    Ok(hash)
///}
///
/// #[tokio::main]
/// async fn main() -> Result<(), std::io::Error> {
///     // Example: In-memory data.
///     let data = b"Hello, world!"; // A byte slice.
///     let reader = Cursor::new(data); // Create an in-memory AsyncRead.