Interface TransportBackend

All Superinterfaces:
AutoCloseable
All Known Implementing Classes:
IoUringBackend, NioBackend

public interface TransportBackend extends AutoCloseable
Backend abstraction for pluggable I/O implementations.

This interface defines the low-level I/O operations that can be implemented by different backends (io_uring, NIO, etc.). It provides a consistent API for the transport layer while allowing backend-specific optimizations.

Supported Backends

Available Backend Implementations
BackendPlatformFeaturesPerformance
io_uring Linux 5.1+ Registered buffers, batch submission, SQPOLL Highest (1.7x NIO)
NIO All platforms Standard Java NIO, selector-based Baseline
XDP Linux 4.8+ (future) Kernel bypass via eBPF Ultra-low latency
DPDK Linux (future) Full kernel bypass, PMD drivers Maximum throughput

Registered Buffers

Backends that support registered buffers (io_uring, DPDK) implement supportsRegisteredBuffers() returning true. Registration pre-validates memory regions with the kernel, eliminating per-operation overhead:

  • io_uring: Uses io_uring_register_buffers() syscall
  • DPDK: Uses IOVA-contiguous memory pools
  • NIO: No registration (falls back to copy)

Batch Submission

High-performance backends implement batch submission via submitBatch():

  • Syscall reduction: One syscall submits multiple operations (100x reduction)
  • Ring buffer efficiency: Operations queue in user space, submitted atomically
  • Adaptive batching: Collect operations then submit periodically or when full

Operation Flow

1. Queue operations: connect(), send(), receive()
   └─> Added to submission queue (no syscall)

2. Submit batch: submitBatch()
   └─> Single syscall submits all queued ops

3. Wait for completions: poll() or waitForCompletion()
   └─> CompletionHandler called for each complete op

Token-Based Correlation

Each operation accepts a token parameter that is preserved through completion. This allows applications to track operations without additional allocation or data structures.

See Also:
  • Method Details

    • initialize

      void initialize(TransportConfig config)
      Initializes the backend with the given configuration.

      This is called once during transport creation. Implementations should allocate resources, initialize the I/O subsystem, and prepare for operations.

      Parameters:
      config - the transport configuration
      Throws:
      TransportException - if initialization fails
    • registerBufferPool

      void registerBufferPool(RegisteredBufferPool bufferPool)
      Registers a buffer pool with this backend for zero-copy I/O.

      For io_uring, this calls io_uring_register_buffers() to pre-register memory regions with the kernel. For other backends, this may be a no-op.

      Parameters:
      bufferPool - the buffer pool to register
      Throws:
      UnsupportedOperationException - if backend doesn't support registered buffers
    • connect

      void connect(SocketAddress remoteAddress, long token)
      Connects to a remote endpoint asynchronously.
      Parameters:
      remoteAddress - the remote address to connect to
      token - the token identifying the operation
    • bind

      void bind(SocketAddress localAddress)
      Binds to a local address for accepting connections (server mode).
      Parameters:
      localAddress - the local address to bind to
    • accept

      void accept(long token)
      Accepts an incoming connection (server mode).
      Parameters:
      token - the token identifying the operation
    • send

      void send(RegisteredBuffer buffer, long token)
      Sends data using a registered buffer (zero-copy).

      For io_uring, this uses io_uring_prep_send_fixed() with the buffer index. For other backends, this may fall back to a regular send.

      Parameters:
      buffer - the registered buffer containing data to send
      token - the token identifying the operation
    • send

      void send(MemorySegment data, int length, long token)
      Sends data using a raw memory segment.

      This is a fallback for non-registered buffers. Less efficient than send(RegisteredBuffer, long) but more flexible.

      Parameters:
      data - the memory segment containing data to send
      length - the number of bytes to send
      token - the token identifying the operation
    • receive

      void receive(RegisteredBuffer buffer, long token)
      Receives data into a registered buffer (zero-copy).

      For io_uring, this uses io_uring_prep_recv_fixed() with the buffer index.

      Parameters:
      buffer - the registered buffer to receive into
      token - the token identifying the operation
    • receive

      void receive(MemorySegment data, int maxLength, long token)
      Receives data into a raw memory segment.
      Parameters:
      data - the memory segment to receive into
      maxLength - the maximum number of bytes to receive
      token - the token identifying the operation
    • submitBatch

      int submitBatch()
      Submits all queued operations in a batch.

      For io_uring, this calls io_uring_submit() to submit all queued operations with a single syscall. This is the key to achieving 100x syscall reduction.

      For NIO, this is typically a no-op since NIO doesn't support batching.

      Returns:
      the number of operations submitted
    • poll

      int poll(CompletionHandler handler)
      Polls for completions without blocking.

      For io_uring, this calls io_uring_peek_cqe() to check for completed operations. For NIO, this may use a Selector with 0 timeout.

      Parameters:
      handler - the handler to call for each completion
      Returns:
      the number of operations completed
    • waitForCompletion

      int waitForCompletion(long timeoutMillis, CompletionHandler handler)
      Waits for at least one operation to complete.

      This blocks until at least one queued operation completes.

      Parameters:
      timeoutMillis - the maximum time to wait in milliseconds (0 = forever)
      handler - the handler to call for each completion
      Returns:
      the number of operations completed
    • supportsRegisteredBuffers

      boolean supportsRegisteredBuffers()
      Returns whether this backend supports registered buffers.
      Returns:
      true if registered buffers are supported
    • supportsBatchSubmission

      boolean supportsBatchSubmission()
      Returns whether this backend supports batch submission.
      Returns:
      true if batch submission is supported
    • supportsTLS

      boolean supportsTLS()
      Returns whether this backend supports TLS/SSL.
      Returns:
      true if TLS is supported
    • getBackendType

      String getBackendType()
      Returns the backend type identifier.
      Returns:
      the backend type (e.g., "io_uring", "nio", "xdp")
    • getStats

      BackendStats getStats()
      Returns statistics about backend operations.
      Returns:
      backend statistics including operation counts, errors, etc.
    • close

      void close()
      Closes the backend and releases all resources.
      Specified by:
      close in interface AutoCloseable
    • createFromAccepted

      TransportBackend createFromAccepted(int handle)
      Creates a new backend instance from an accepted connection handle.

      For io_uring, the handle is the file descriptor. For NIO, the handle is an index or reference to the accepted channel.

      Parameters:
      handle - the handle returned by the accept completion
      Returns:
      a new TransportBackend for the accepted connection