Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Concurrency, Parallelism, and Processes

Ordinary pipelines are lazy, not parallel

Most builtin pipelines are synchronous iterator chains. Stages overlap only in the sense that downstream demand drives upstream computation on the same thread. This yields bounded memory and early termination without scheduling, channels, or async state machines.

External processes create operating-system concurrency

run-external connects a ByteStream directly to child stdin when possible. If structured data must be encoded, a named worker thread copies it into the pipe. Child stdout/stderr remain lazy byte readers; another thread waits for exit status so pipe consumption and process completion can progress together.

par-each opts into CPU parallelism

par-each uses dedicated Rayon pools. Top-level calls reuse pools by requested thread count. Nested calls create a private pool: sharing the outer pool could deadlock when a streaming consumer blocks while occupying a worker needed by its producer.

Unordered mode streams results through a bounded channel of 64 items. Ordered mode attaches indices, collects, and parallel-sorts before returning—making memory/latency the explicit price of deterministic order.

Plugins bridge streams with protocol messages

Plugin interfaces send a header describing empty/value/list/bytes, then stream messages on separate flow-control machinery. Background writers prevent a bidirectional plugin protocol from deadlocking the evaluator while it awaits a response that depends on consumed input.

This repository demonstrates that concurrency should be introduced per semantic need: lazy pull for pipelines, OS processes for tools, Rayon for independent closures, and channels/threads for duplex bridges.