wireform-core-0.2.0.0: src/Wireform/Transport/Config.hs
module Wireform.Transport.Config (
-- * Profiles
Profile (..),
profileConfig,
-- * Full configuration
TransportConfig (..),
defaultTransportConfig,
-- * Wait policy
WaitPolicy (..),
SpinBudget (..),
-- * Pinning
PinningPolicy (..),
-- * Pages
PagePolicy (..),
-- * NUMA
NumaPolicy (..),
-- * io_uring
IOUringConfig (..),
SQPollPolicy (..),
CompletionWaitMode (..),
defaultIOUringConfig,
-- * Capability handling
CapabilityAction (..),
) where
------------------------------------------------------------------------
-- Profiles
------------------------------------------------------------------------
{- | High-level performance profile. Most users pick one of these
and never touch 'TransportConfig' directly.
-}
data Profile
= -- | IO-manager-parked. Good citizen on shared systems.
Throughput
| -- | Brief spin before parking, pinned thread, huge pages where available.
LowLatency
| {- | Pure busy-poll, pinned to isolated core, huge pages, mlock.
Burns one CPU core permanently.
-}
UltraLowLatency
deriving stock (Eq, Ord, Show, Read, Bounded, Enum)
-- | Expand a profile into a full 'TransportConfig'.
profileConfig :: Profile -> TransportConfig
profileConfig Throughput = defaultTransportConfig
profileConfig LowLatency =
defaultTransportConfig
{ waitPolicy = WaitSpinThenPark (SpinNanos 5000)
, pinning = PinNearFd
, pages = PreferHugePages
, memoryLocking = True
, numaPlacement = NumaAutoFromFd
}
profileConfig UltraLowLatency =
defaultTransportConfig
{ waitPolicy = WaitBusyPoll
, pinning = PinIsolated
, pages = PreferHugePages
, memoryLocking = True
, numaPlacement = NumaAutoFromFd
, ioUring =
defaultIOUringConfig
{ ioUringQueueDepth = 1024
, ioUringSQPoll = SQPollWithIdle 100
, ioUringCompletionWait = WaitViaBusyPoll
}
}
------------------------------------------------------------------------
-- Full configuration
------------------------------------------------------------------------
data TransportConfig = TransportConfig
{ ringSizeHint :: !Int
{- ^ Requested ring size in bytes. Rounded up to page-size multiple
and power of two. Default: 1 MiB.
-}
, waitPolicy :: !WaitPolicy
, pinning :: !PinningPolicy
, pages :: !PagePolicy
, memoryLocking :: !Bool
-- ^ @mlock@ the ring. Requires sufficient RLIMIT_MEMLOCK.
, numaPlacement :: !NumaPolicy
, ioUring :: !IOUringConfig
-- ^ Linux io_uring tuning (silently ignored elsewhere).
, onCapabilityLimit :: !CapabilityAction
-- ^ What to do when a knob cannot be applied on this platform.
}
deriving stock (Show)
defaultTransportConfig :: TransportConfig
defaultTransportConfig =
TransportConfig
{ ringSizeHint = 1024 * 1024
, waitPolicy = WaitParkImmediately
, pinning = NoPinning
, pages = StandardPages
, memoryLocking = False
, numaPlacement = NoNumaPreference
, ioUring = defaultIOUringConfig
, onCapabilityLimit = LogAndContinue
}
------------------------------------------------------------------------
-- Wait policy
------------------------------------------------------------------------
data WaitPolicy
= -- | Park on the IO manager as soon as caught up.
WaitParkImmediately
| -- | Busy-spin for the budget, then park.
WaitSpinThenPark !SpinBudget
| -- | Never park. Burns a core.
WaitBusyPoll
deriving stock (Show)
data SpinBudget
= SpinIterations !Int
| SpinNanos !Int
| SpinUntilPaused
deriving stock (Show)
------------------------------------------------------------------------
-- Pinning
------------------------------------------------------------------------
data PinningPolicy
= NoPinning
| PinToCore !Int
| PinToCoreSet ![Int]
| -- | Auto-detect: pin near the NIC / fd's NUMA node.
PinNearFd
| -- | Pick an isolated core (Linux @isolcpus=@); fall back to 'PinNearFd'.
PinIsolated
deriving stock (Show)
------------------------------------------------------------------------
-- Page policy
------------------------------------------------------------------------
data PagePolicy
= StandardPages
| -- | Request huge pages; fall back to standard if unavailable.
PreferHugePages
| -- | Fail at ring creation if huge pages are unavailable.
RequireHugePages
deriving stock (Show)
------------------------------------------------------------------------
-- NUMA
------------------------------------------------------------------------
data NumaPolicy
= NoNumaPreference
| NumaNode !Int
| NumaAutoFromFd
| NumaAutoFromCurrentCore
deriving stock (Show)
------------------------------------------------------------------------
-- io_uring
------------------------------------------------------------------------
data IOUringConfig = IOUringConfig
{ ioUringQueueDepth :: !Int
, ioUringSQPoll :: !SQPollPolicy
, ioUringProvidedBuffers :: !Bool
, ioUringCompletionWait :: !CompletionWaitMode
}
deriving stock (Show)
defaultIOUringConfig :: IOUringConfig
defaultIOUringConfig =
IOUringConfig
{ ioUringQueueDepth = 128
, ioUringSQPoll = NoSQPoll
, ioUringProvidedBuffers = True
, ioUringCompletionWait = WaitViaEventFd
}
data SQPollPolicy
= NoSQPoll
| SQPollWithIdle !Int
deriving stock (Show)
data CompletionWaitMode
= WaitViaEventFd
| WaitViaBusyPoll
deriving stock (Show)
------------------------------------------------------------------------
-- Capability action
------------------------------------------------------------------------
data CapabilityAction
= SilentlyIgnore
| LogAndContinue
| FailHard
deriving stock (Eq, Ord, Show, Read, Bounded, Enum)