HORIZON HASKELLDocslts/ghc-9.14.xd82dee82026-10-12Search names, modules, packages, or :: a typeCtrl K

GHC 9.14.1 · lts/ghc-9.14.x · d82dee8 · 2026-10-12

Moduleblockio-uring-0.2.0.0GHC2021

System.IO.BlockIO

  • 6 types
  • 5 values

I/O context and initialisation

6 declarations
newtypenewtype IOCtx
#

IO context: a handle used by threads submitting IO batches.

Internally, each GHC capability in the program creates its own independent IO context. This means that each capability can process batches of I/O operations independently. As such, running with more capabilities can increase throughput.

datadata IOCtxParams
#

Parameters for instantiating an IOCtx IO context.

Picking suitable parameters for high performance depends on the hardware that is used and the workload of the program. There are benchmarks included in the blockio-uring repository that can help gauge the performance for a random 4k read workload, but some trial and error with custom benchmarks might be required.

Ideally the concurrency limit should be a multiple of the batch size limit. This should ensure that there can be multiple batches in flight at once. If so, the SSD can more often than not pick up new I/O batches to perform as soon as it has finished other batches.

Ideally the batch size limit should be equal to if not larger than the number of I/O operations that an SSD can perform concurrently. This ensures that the SSD can perform most if not all I/O operations in a batch concurrently.

Internally, each GHC capability in the program creates its own independent IO context. These parameters apply separately to each capability's IO context. For example, if the program runs with 2 capabilities, a batch size limit of 64, and a concurrency limit of 256, then each capability gets its own IO context, and each IO context can process batches of at most 64 I/O operations at a time, and each IO context can only process 4 such batches concurrently.

Constructors

  • IOCtxParams
    • ioctxBatchSizeLimit :: !Int

      The maximum size of a batch of I/O operations that can be processed as a whole.

      Note that his does not affect the size of batches of I/O operations that can be submitted using submitIO. There is no restriction on the size of batches submitted using submitIO. If the size of a batch that is passed to submitIO exceeds this limit, then internally these batches will split into sub-batches of size at most the limit, and each sub-batch is processed individually.

    • ioctxConcurrencyLimit :: !Int

      The total number of I/O operations that can be processed concurrently.

      If a use of submitIO would lead to this limit being exceeded, then the call to submitIO will block until enough I/O batches have been processed.

    • ioctxIOWaitMetrics :: !Bool

      Enable or disable IOWAIT metrics

      If io_uring_set_iowait(3) is available, then it will be called with this value to either enable (True) or disable (False) IOWAIT metrics. This is innocuous in terms of performance but changes how CPU idle time is reported. io_uring_set_iowait(3) is available for liburing versions >= 2.10 and Linux kernels versions >= 6.15.

Instances1Show

Performing I/O

7 declarations

Submit a batch of I/O operations, and wait for them all to complete. The sequence of results matches up with the sequence of operations. Any I/O errors are reported in the result list, not as IO exceptions.

Note that every operation in the batch is performed concurrently with respect to each other (and any other concurrent batches): their effects may be performed in any order. It is up to you to ensure the effects do not interfere with each other (i.e. not mixing reads and writes to overlapping areas of files).

It is permitted to submit multiple batches concurrently from different Haskell threads. Submitting I/O only blocks the calling Haskell thread, it does not block other Haskell threads. The maximum concurrency is set when the IOCtx is created: submitting more operations than this will block until enough previous operations have completed.

Performance tips:

  • Use reasonable batch sizes to amortise the overheads over multiple operations. Batch sizes that are within the I/O limit of the IOCtx can be initiated with a single system call.

  • Consider that most SSDs can perform up to 64 operations concurrently. So use reasonable batch sizes, and submit multiple batches concurrently.

  • Think of I/O as a queue, with I/O operations being added at one end, and results arriving at the other: keep the queue full with 64 operations in progress at once.

  • Pipeline your I/O submissions to keep the queue full: submit enough batches to keep the queue full, and as batches complete, submit more. For example follow a strategy of submitting batches up to double the target SSD queue depth (i.e. 2x 64 = 128) and when it drains to nearly the target depth, fill it up to double again. This way there is always at least the target number in flight at once.

newtypenewtype IOResult
#
Instances7Eq, Show, Unbox, MVector, Vector, …
newtypenewtype Errno
#

Haskell representation for errno values. The implementation is deliberately exposed, to allow users to add their own definitions of Errno values.

Constructors

Instances1Eq
  • Eq ErrnoDefined in ghc-internal-9.1401.0 · GHC.Internal.Foreign.C.Error