Myra Transport Quickstart

Early Development Notice

All MVP.Express projects are currently in active development (pre-1.0.0) and should not be used in production environments. APIs may change without notice, and breaking changes are expected until each project reaches version 1.0.0. We welcome early adopters and contributors, but please use at your own risk.

Build ultra-low-latency network services with io_uring.

Prerequisites

  • Java 24+ with preview features enabled
  • Linux kernel 5.19+ (for io_uring)
  • Gradle 8.5+ or Maven 3.9+

Installation

Add to your build.gradle.kts:

dependencies {
    implementation("express.mvp.myra:myra-transport:0.1.0-SNAPSHOT")
}

Quick Server Example

import express.mvp.myra.transport.*;

public class EchoServer {
    public static void main(String[] args) {
        var config = TransportConfig.builder()
            .port(8080)
            .ringSize(256)              // io_uring ring size
            .bufferSize(4096)           // Per-connection buffer
            .maxConnections(1000)
            .build();
        
        var server = MyraServer.create(config, new EchoHandler());
        
        System.out.println("Echo server listening on port 8080");
        server.start();  // Blocks until shutdown
    }
}

class EchoHandler implements MessageHandler {
    @Override
    public void onMessage(Connection conn, MemorySegment data, int length) {
        // Echo the data back - zero-copy!
        conn.write(data, 0, length);
    }
    
    @Override
    public void onConnect(Connection conn) {
        System.out.println("Client connected: " + conn.remoteAddress());
    }
    
    @Override
    public void onDisconnect(Connection conn) {
        System.out.println("Client disconnected: " + conn.remoteAddress());
    }
}

Quick Client Example

import express.mvp.myra.transport.*;

public class EchoClient {
    public static void main(String[] args) {
        var client = MyraClient.connect("localhost", 8080);
        
        try (Arena arena = Arena.ofConfined()) {
            var buffer = arena.allocate(1024);
            
            // Write message to buffer
            String message = "Hello, Myra!";
            buffer.setString(0, message, StandardCharsets.UTF_8);
            
            // Send and receive
            client.write(buffer, 0, message.length());
            int received = client.read(buffer, 0, 1024);
            
            String response = buffer.getString(0, StandardCharsets.UTF_8);
            System.out.println("Received: " + response);
        }
        
        client.close();
    }
}

Configuration Options

OptionDefaultDescription
ringSize256io_uring submission queue size
bufferSize4096Per-connection receive buffer
maxConnections10000Maximum concurrent connections
sqPollfalseEnable kernel-side SQ polling
registerBufferstruePre-register buffers with kernel

Performance Tips

  1. Tune ring size: Larger rings reduce syscalls under load
  2. Enable SQ polling: For sub-microsecond latency (requires CAP_SYS_NICE)
  3. Pre-allocate buffers: Use the memory pool to avoid allocation during I/O

JVM Arguments

java --enable-preview \
     --enable-native-access=ALL-UNNAMED \
     -Dio.uring.sqpoll=true \
     -jar myapp.jar

Next Steps