davidtos/JUring

JUring provides Java bindings for io_uring

Java

201

26 commits

updated May 7, 2026

See the code

README

JUring: File I/O for Java using IO_uring

JUring is a Java library that provides bindings to Linux's io_uring asynchronous I/O interface using Java's Foreign Function & Memory API. JUring can deliver significant performance improvements over standard Java FileChannel operations, particularly for high-throughput file I/O workloads.

Performance

Key Performance Highlights

JUring with registered files provides the following performance:

  • Up to 489% faster than pre-opened FileChannels at 4KB buffer sizes for reads
  • 55% faster at 512-byte operations, handling over 29,000 operations per millisecond
  • Write performance matching or exceeding FileChannel performance across buffer sizes
  • Scalability across multiple concurrent threads (1-25 threads tested)

Benchmark Results

All benchmarks were conducted on a Linux machine using JMH (Java Microbenchmark Harness) with 2,211 operations per test invocation.

Read Performance: Optimized File Access (25 threads)

Comparing registered files vs pre-opened FileChannels:

Buffer SizeRegistered Files (ops/ms)Pre-opened FileChannels (ops/ms)Improvement
512 bytes29,02318,769+55%
4KB13,3932,275+489%
16KB679554+23%
64KB150129+16%

Read Performance: JUring vs FileChannel Operations (25 threads)

Comparing different I/O approaches with open/read/close patterns:

Buffer SizeJUring Open/Read/Close (ops/ms)FileChannel Open/Read/Close (ops/ms)Improvement
512 bytes1,252968+29%
4KB1,268855+48%
16KB563445+27%
64KB141125+13%

The goal of this benchmark is to open a file, read the given buffer size, and close it again. Opening and closing the files is the heavy part of this benchmark.

Read Performance: Blocking I/O with Virtual Threads (25 threads)

Comparing JUring blocking vs FileChannel with Virtual Threads:

Buffer SizeJUring Blocking + VThreads (ops/ms)FileChannel + VThreads (ops/ms)Improvement
512 bytes1,051923+14%
4KB1,029710+45%
16KB788350+125%
64KB286120+138%

Write Performance Scaling

JUring registered files vs pre-opened FileChannels across different thread counts:

Single Thread:

Buffer SizeJUring (ops/ms)FileChannel (ops/ms)Improvement
512 bytes891400+123%
4KB860260+231%
16KB498144+246%
64KB15153+185%

8 Threads:

Buffer SizeJUring (ops/ms)FileChannel (ops/ms)Improvement
512 bytes4,2922,429+77%
4KB3,0131,724+75%
16KB1,189895+33%
64KB286294-3%

20 Threads:

Buffer SizeJUring (ops/ms)FileChannel (ops/ms)Improvement
512 bytes5,2005,2040%
4KB3,3813,440-2%
16KB1,2111,449-16%
64KB233346-33%

When to Use JUring

JUring excels in scenarios with:

  • High-throughput file I/O operations (thousands of ops/ms)
  • Applications that can pre-register files for optimal performance
  • Workloads with small to medium buffer sizes (512B - 16KB)
  • Single-threaded or lightly-threaded write operations
  • Mixed read/write workloads where read performance is critical

Consider standard FileChannel for:

  • High-concurrency write operations (20+ threads)
  • Large buffer sizes (64KB+) with many concurrent writers
  • Applications requiring broad platform compatibility
  • Occasional file operations
  • Simplicity (Working on this!)

Benchmark Methodology

The benchmarks use JMH (Java Microbenchmark Harness) with the following configuration:

  • Operations per test: 2,211 operations per invocation, each thread has to process a given list of files and offsets
  • Queue depth: 256 inflight requests
  • Access pattern: Random offsets within files
  • Thread counts: 1, 8, 20, and 25 concurrent threads (varies by test)
  • Buffer sizes: 512 bytes, 4KB, 16KB, 64KB
  • Warmup: Ring initialization performed outside benchmark timing

Benchmark Categories

  • registeredFiles: io_uring with pre-registered file descriptors (optimal performance)
  • preOpenedFileChannels: FileChannel with pre-opened file handles
  • juringOpenReadClose: JUring with full open/read/close cycle
  • fileChannelOpenReadClose: FileChannel with full open/read/close cycle
  • juringBlockingWithVirtualThreads: JUring blocking API with Virtual Threads
  • fileChannelOpenReadCloseOnVirtualThreads: FileChannel with Virtual Threads

For complete benchmark source code and detailed methodology, see the test files in the repository src/test/java/bench/random.

Requirements

  • Linux kernel 5.1 or higher
  • liburing installed
  • Java 22 or higher (for Foreign Function & Memory API)

Current Limitations and Future Improvements

Points of interest

  • Read operations: JUring shows consistent advantages, especially with registered files
  • Write operations: Performance advantages diminish at high concurrency (20+ threads)
  • Sweet spot: 4KB buffer size shows the most dramatic improvements for reads
  • Scaling: JUring shows better scaling characteristics for single-threaded operations

Known Limitations

  • Initialization overhead: Creating JUring instances takes a few milliseconds
  • Platform dependency: Linux-only due to io_uring requirement
  • High concurrency writes: FileChannel may perform better with many concurrent writers

Planned Improvements

  • Ring pooling for reduced initialization costs
  • Write performance optimization for high-concurrency scenarios
  • Additional io_uring features (file modes, flags, sockets)
  • Enhanced blocking API performance
  • Improved memory cleanup strategies

Creating the benchmark files

If you want to run the benchmark yourself, you can use the following:

seq 1 2211 | xargs -P 8 -I {} bash -c 'yes "{} " | head -c 5242880 > "file_{}.bin"'
iouring
java

Contributors

davidtos

25 commits

yasht-007

1 commits

davidtos/JUring

JUring provides Java bindings for io_uring

Java

201

26 commits

updated May 7, 2026

See the code

README

JUring: File I/O for Java using IO_uring

JUring is a Java library that provides bindings to Linux's io_uring asynchronous I/O interface using Java's Foreign Function & Memory API. JUring can deliver significant performance improvements over standard Java FileChannel operations, particularly for high-throughput file I/O workloads.

Performance

Key Performance Highlights

JUring with registered files provides the following performance:

  • Up to 489% faster than pre-opened FileChannels at 4KB buffer sizes for reads
  • 55% faster at 512-byte operations, handling over 29,000 operations per millisecond
  • Write performance matching or exceeding FileChannel performance across buffer sizes
  • Scalability across multiple concurrent threads (1-25 threads tested)

Benchmark Results

All benchmarks were conducted on a Linux machine using JMH (Java Microbenchmark Harness) with 2,211 operations per test invocation.

Read Performance: Optimized File Access (25 threads)

Comparing registered files vs pre-opened FileChannels:

Buffer SizeRegistered Files (ops/ms)Pre-opened FileChannels (ops/ms)Improvement
512 bytes29,02318,769+55%
4KB13,3932,275+489%
16KB679554+23%
64KB150129+16%

Read Performance: JUring vs FileChannel Operations (25 threads)

Comparing different I/O approaches with open/read/close patterns:

Buffer SizeJUring Open/Read/Close (ops/ms)FileChannel Open/Read/Close (ops/ms)Improvement
512 bytes1,252968+29%
4KB1,268855+48%
16KB563445+27%
64KB141125+13%

The goal of this benchmark is to open a file, read the given buffer size, and close it again. Opening and closing the files is the heavy part of this benchmark.

Read Performance: Blocking I/O with Virtual Threads (25 threads)

Comparing JUring blocking vs FileChannel with Virtual Threads:

Buffer SizeJUring Blocking + VThreads (ops/ms)FileChannel + VThreads (ops/ms)Improvement
512 bytes1,051923+14%
4KB1,029710+45%
16KB788350+125%
64KB286120+138%

Write Performance Scaling

JUring registered files vs pre-opened FileChannels across different thread counts:

Single Thread:

Buffer SizeJUring (ops/ms)FileChannel (ops/ms)Improvement
512 bytes891400+123%
4KB860260+231%
16KB498144+246%
64KB15153+185%

8 Threads:

Buffer SizeJUring (ops/ms)FileChannel (ops/ms)Improvement
512 bytes4,2922,429+77%
4KB3,0131,724+75%
16KB1,189895+33%
64KB286294-3%

20 Threads:

Buffer SizeJUring (ops/ms)FileChannel (ops/ms)Improvement
512 bytes5,2005,2040%
4KB3,3813,440-2%
16KB1,2111,449-16%
64KB233346-33%

When to Use JUring

JUring excels in scenarios with:

  • High-throughput file I/O operations (thousands of ops/ms)
  • Applications that can pre-register files for optimal performance
  • Workloads with small to medium buffer sizes (512B - 16KB)
  • Single-threaded or lightly-threaded write operations
  • Mixed read/write workloads where read performance is critical

Consider standard FileChannel for:

  • High-concurrency write operations (20+ threads)
  • Large buffer sizes (64KB+) with many concurrent writers
  • Applications requiring broad platform compatibility
  • Occasional file operations
  • Simplicity (Working on this!)

Benchmark Methodology

The benchmarks use JMH (Java Microbenchmark Harness) with the following configuration:

  • Operations per test: 2,211 operations per invocation, each thread has to process a given list of files and offsets
  • Queue depth: 256 inflight requests
  • Access pattern: Random offsets within files
  • Thread counts: 1, 8, 20, and 25 concurrent threads (varies by test)
  • Buffer sizes: 512 bytes, 4KB, 16KB, 64KB
  • Warmup: Ring initialization performed outside benchmark timing

Benchmark Categories

  • registeredFiles: io_uring with pre-registered file descriptors (optimal performance)
  • preOpenedFileChannels: FileChannel with pre-opened file handles
  • juringOpenReadClose: JUring with full open/read/close cycle
  • fileChannelOpenReadClose: FileChannel with full open/read/close cycle
  • juringBlockingWithVirtualThreads: JUring blocking API with Virtual Threads
  • fileChannelOpenReadCloseOnVirtualThreads: FileChannel with Virtual Threads

For complete benchmark source code and detailed methodology, see the test files in the repository src/test/java/bench/random.

Requirements

  • Linux kernel 5.1 or higher
  • liburing installed
  • Java 22 or higher (for Foreign Function & Memory API)

Current Limitations and Future Improvements

Points of interest

  • Read operations: JUring shows consistent advantages, especially with registered files
  • Write operations: Performance advantages diminish at high concurrency (20+ threads)
  • Sweet spot: 4KB buffer size shows the most dramatic improvements for reads
  • Scaling: JUring shows better scaling characteristics for single-threaded operations

Known Limitations

  • Initialization overhead: Creating JUring instances takes a few milliseconds
  • Platform dependency: Linux-only due to io_uring requirement
  • High concurrency writes: FileChannel may perform better with many concurrent writers

Planned Improvements

  • Ring pooling for reduced initialization costs
  • Write performance optimization for high-concurrency scenarios
  • Additional io_uring features (file modes, flags, sockets)
  • Enhanced blocking API performance
  • Improved memory cleanup strategies

Creating the benchmark files

If you want to run the benchmark yourself, you can use the following:

seq 1 2211 | xargs -P 8 -I {} bash -c 'yes "{} " | head -c 5242880 > "file_{}.bin"'
iouring
java

Contributors

davidtos

25 commits

yasht-007

1 commits

Languages

Java

99.8%