LMAX-Exchange/disruptor
High Performance Inter-Thread Messaging Library
Healthy across all four use cases
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓14 active contributors
- ✓Apache-2.0 licensed
- ✓CI configured
Show all 6 evidence items →Show less
- ✓Tests present
- ⚠Stale — last commit 1y ago
- ⚠Concentrated ownership — top contributor handles 61% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/lmax-exchange/disruptor)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/lmax-exchange/disruptor on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: LMAX-Exchange/disruptor
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/LMAX-Exchange/disruptor shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across all four use cases
- 14 active contributors
- Apache-2.0 licensed
- CI configured
- Tests present
- ⚠ Stale — last commit 1y ago
- ⚠ Concentrated ownership — top contributor handles 61% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live LMAX-Exchange/disruptor
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/LMAX-Exchange/disruptor.
What it runs against: a local clone of LMAX-Exchange/disruptor — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in LMAX-Exchange/disruptor | Confirms the artifact applies here, not a fork |
| 2 | License is still Apache-2.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 431 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of LMAX-Exchange/disruptor. If you don't
# have one yet, run these first:
#
# git clone https://github.com/LMAX-Exchange/disruptor.git
# cd disruptor
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of LMAX-Exchange/disruptor and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "LMAX-Exchange/disruptor(\\.git)?\\b" \\
&& ok "origin remote is LMAX-Exchange/disruptor" \\
|| miss "origin remote is not LMAX-Exchange/disruptor (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is Apache-2.0" \\
|| miss "license drift — was Apache-2.0 at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "src/main/java/com/lmax/disruptor/Disruptor.java" \\
&& ok "src/main/java/com/lmax/disruptor/Disruptor.java" \\
|| miss "missing critical file: src/main/java/com/lmax/disruptor/Disruptor.java"
test -f "src/main/java/com/lmax/disruptor/RingBuffer.java" \\
&& ok "src/main/java/com/lmax/disruptor/RingBuffer.java" \\
|| miss "missing critical file: src/main/java/com/lmax/disruptor/RingBuffer.java"
test -f "src/main/java/com/lmax/disruptor/Sequencer.java" \\
&& ok "src/main/java/com/lmax/disruptor/Sequencer.java" \\
|| miss "missing critical file: src/main/java/com/lmax/disruptor/Sequencer.java"
test -f "src/main/java/com/lmax/disruptor/WaitStrategy.java" \\
&& ok "src/main/java/com/lmax/disruptor/WaitStrategy.java" \\
|| miss "missing critical file: src/main/java/com/lmax/disruptor/WaitStrategy.java"
test -f "src/main/java/com/lmax/disruptor/EventHandler.java" \\
&& ok "src/main/java/com/lmax/disruptor/EventHandler.java" \\
|| miss "missing critical file: src/main/java/com/lmax/disruptor/EventHandler.java"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 431 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~401d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/LMAX-Exchange/disruptor"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
LMAX Disruptor is a high-performance inter-thread messaging library that implements a lock-free ring buffer (circular array) for ultra-low-latency event passing between threads. It replaces traditional queue-based designs with a pre-allocated ring buffer that reduces garbage collection pauses and CPU cache misses, making it ideal for latency-sensitive systems like financial trading platforms where nanosecond-scale performance matters. Modular Gradle project (Java 11+ source/target): core ring buffer implementation lives in src/main/java under module com.lmax.disruptor, comprehensive test suite in src/test, performance benchmarks in gradle/jmh.gradle and gradle/perf.gradle, JCStress concurrency tests via gradle/jcstress.gradle, and documentation as AsciiDoc files in src/docs/asciidoc (user guide, developer guide, changelog). Gradle build orchestrates checkstyle validation, publishing, and packaging via bnd (OSGi bundle support).
👥Who it's for
Systems engineers and developers building ultra-low-latency applications—particularly in financial trading, real-time analytics, and high-frequency systems—who need to pass events between threads without the GC overhead and contention of traditional concurrent queues. Contributors are typically those optimizing JVM applications for extreme performance requirements.
🌱Maturity & risk
Highly mature and production-ready: v4.0.0 in development (snapshot), extensive test coverage via JUnit 5 and JCStress, CI/CD pipeline with GitHub Actions (Gradle build, CodeQL analysis, JCStress regression tests), and maintained by LMAX Development Team. Active codebase with professional testing infrastructure and formal documentation (user guide, developer guide, JavaDoc).
Standard open source risks apply.
Active areas of work
Version 4.0.0 is in snapshot/development phase. The project maintains active CI pipelines for Gradle builds, CodeQL static analysis, and JCStress concurrency regression testing. Documentation is being maintained in AsciiDoc format with user guides and developer guides in src/docs/asciidoc/en/. The pre-commit hook infrastructure (.githooks/pre-commit) suggests active developer experience improvements.
🚀Get running
git clone git@github.com:LMAX-Exchange/disruptor.git
cd disruptor
./gradlew build
./gradlew test
Or via https if SSH is not configured: git clone https://github.com/LMAX-Exchange/disruptor.git. Gradle wrapper (gradlew) requires Java 11+; it will download Gradle 7.6 automatically.
Daily commands:
No server to run—Disruptor is an embeddable library. To verify it works: ./gradlew test runs the test suite. To run performance benchmarks: ./gradlew jmh executes JMH benchmarks. To run concurrency stress tests: ./gradlew jcstress (see gradle/jcstress.gradle). To build JavaDoc: ./gradlew javadoc. To build AsciiDoc docs: ./gradlew asciidoctor.
🗺️Map of the codebase
src/main/java/com/lmax/disruptor/Disruptor.java— Core facade orchestrating the entire ring buffer setup, event handlers, and producer/consumer lifecycle—entry point for all userssrc/main/java/com/lmax/disruptor/RingBuffer.java— Central lock-free circular data structure enabling wait-free publishing and consumption—the performance foundation of the librarysrc/main/java/com/lmax/disruptor/Sequencer.java— Abstract base for sequence coordination between producers and consumers; implements single/multi-producer variants critical for thread safetysrc/main/java/com/lmax/disruptor/WaitStrategy.java— Interface defining consumer blocking strategies (busy-spin, parking, blocking); fundamental to latency/throughput tradeoffssrc/main/java/com/lmax/disruptor/EventHandler.java— Simple callback interface for event processing; all user event handlers implement this—defines the contract for consumer logicbuild.gradle— Gradle build script defining dependencies, test frameworks (JUnit, jcstress), performance benchmarks (JMH), and publication to Maven Centralsrc/docs/asciidoc/en/user-guide/10_using_the_disruptor.adoc— Primary user documentation explaining Disruptor setup, API patterns, and common pitfalls—required reading before implementing integration
🛠️How to make changes
Add a Custom Event Handler
- Define your event class or use existing event object (e.g., LongEvent) (
src/examples/java/com/lmax/disruptor/examples/support/LongEvent.java) - Implement EventHandler<YourEvent> with onEvent() method for processing logic (
src/examples/java/com/lmax/disruptor/examples/longevent/LongEventHandler.java) - In your main setup, register handler via disruptor.handleEventsWith(new YourHandler()) (
src/examples/java/com/lmax/disruptor/examples/longevent/lambdas/LongEventMain.java) - Call disruptor.start() to spawn consumer thread and begin processing (
src/examples/java/com/lmax/disruptor/examples/longevent/lambdas/LongEventMain.java)
Implement Multi-Producer Event Publishing
- Create Disruptor with ProducerType.MULTI in builder (ringBuffer.getProducerType()) (
src/examples/java/com/lmax/disruptor/examples/MultiProducerWithTranslator.java) - Implement EventTranslator<YourEvent> translating external data to ring buffer events (
src/examples/java/com/lmax/disruptor/examples/MultiProducerWithTranslator.java) - Call ringBuffer.publishEvent(translator, externalData) from multiple threads without external sync (
src/examples/java/com/lmax/disruptor/examples/MultiProducerWithTranslator.java) - Verify MultiProducerSequencer is automatically chosen (uses CAS-based claiming with availability bitmap) (
src/main/java/com/lmax/disruptor/MultiProducerSequencer.java)
Configure Latency vs. Throughput Tradeoff
- Choose WaitStrategy in Disruptor builder: BusySpinWaitStrategy (lowest latency), ParkingWaitStrategy (balanced), or BlockingWaitStrategy (lowest CPU) (
src/main/java/com/lmax/disruptor/WaitStrategy.java) - Set ring buffer size power-of-2 (e.g., 1024, 4096); larger = more buffering, less backpressure on producers (
src/main/java/com/lmax/disruptor/RingBuffer.java) - Run JMH benchmarks in gradle/jmh.gradle to measure latency percentiles and throughput for your workload (
gradle/jmh.gradle) - Review src/docs/asciidoc/en/user-guide/20_design_and_implementation.adoc for strategy comparisons and tuning guidance (
src/docs/asciidoc/en/user-guide/20_design_and_implementation.adoc)
Set Up Sequential Handler Dependencies (Pipeline)
- Register first handler via disruptor.handleEventsWith(handler1) (
src/examples/java/com/lmax/disruptor/examples/SequentialThreeConsumers.java) - Chain dependent handlers using disruptor.after(handler1).handleEventsWith(handler2) to enforce ordering (
src/examples/java/com/lmax/disruptor/examples/SequentialThreeConsumers.java) - SequenceBarrier automatically gates handler2 until handler1 completes, ensuring sequential consumption (
src/main/java/com/lmax/disruptor/SequenceBarrier.java) - Verify in src/docs/asciidoc/en/user-guide/10_using_the_disruptor.adoc for multi-handler topology patterns (
src/docs/asciidoc/en/user-guide/10_using_the_disruptor.adoc)
🪤Traps & gotchas
Lock-free pitfalls: Disruptor uses sun.misc.Unsafe for memory barriers and direct memory access. Code is JVM-version and CPU-architecture sensitive; CPU pause instructions (HLT) and cache-line sizes matter. Garbage collection: Pre-allocated ring buffers are designed to avoid GC; if you allocate event objects inside the ring, you negate the entire benefit. Sequencing: Understanding happens-before relationships and memory visibility is non-negotiable—casual use of Disruptor without reading the design guide will produce subtle data races. Java 11+ requirement: sourceCompatibility = JavaVersion.VERSION_11 is enforced; older JVMs are not supported. OSGi bundle: build.gradle uses bnd for module packaging; shade/fat-jar usage patterns may conflict with this metadata.
🏗️Architecture
💡Concepts to learn
- Lock-free Ring Buffer — The core abstraction of Disruptor—a pre-allocated circular array that eliminates locks and malloc/GC overhead by cycling through fixed memory locations, reducing latency variance
- Compare-and-Swap (CAS) Atomics — Disruptor uses CAS instructions (via sun.misc.Unsafe) to coordinate readers/writers without explicit locks; understanding atomic visibility is critical to using it safely
- Cache-line Padding — Disruptor pads objects to cache-line boundaries (typically 64 bytes) to prevent false sharing—where updates to unrelated fields on adjacent memory cause expensive cache coherency traffic
- Wait Strategies (Busy-spin vs Block) — Disruptor offers pluggable strategies for how consumer threads wait for events (spin, park, sleep); selecting the right strategy is a fundamental latency vs. CPU tradeoff
- Happens-before and Memory Barriers — Disruptor relies on JMM (Java Memory Model) guarantees; incorrect barrier placement causes invisible data races. Essential for understanding why certain access patterns are safe
- Single-Writer-Principle (SWP) / SPSC Queues — Disruptor's design assumes single producers or consumers in hot paths; understanding SPSC (Single Producer, Single Consumer) vs. MPMC (Multi) changes coordination overhead
- Event Sourcing & Immutability — Disruptor is often used to stream immutable events between threads; event objects should be reused (not allocated) and treated as write-once to avoid GC and coherency issues
🔗Related repos
JCTools/JCTools— Java Concurrency Tools library; provides alternative lock-free queue implementations (MPMC, SPSC) for lower-level concurrent data structure needs that Disruptor builds uponreactive-streams/reactive-streams-jvm— Standardized async/reactive programming contract for JVM; modern applications often bridge Disruptor events to reactive streams via adaptersOpenHFT/Chronicle-Queue— Built on Disruptor principles; adds persistent event logging and playback, used in financial systems requiring message durability alongside low latencyLMAX-Exchange/event-store— LMAX's own event sourcing library; consumes Disruptor events for building immutable event logs in trading systemsnetty/netty— High-performance network I/O framework; often paired with Disruptor for intra-process event distribution after Netty decodes network packets
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive test coverage for DynamicallyAddHandler example with JUnit 5
The examples directory contains DynamicallyAddHandler.java but there are no corresponding unit tests in src/test. This is a critical use case for dynamic handler management that should have dedicated test coverage to ensure the pattern works correctly and to serve as a reference implementation for users.
- [ ] Create src/test/java/com/lmax/disruptor/examples/DynamicallyAddHandlerTest.java
- [ ] Add tests verifying handlers can be added/removed during Disruptor operation
- [ ] Add tests for thread-safety of dynamic handler addition
- [ ] Add tests verifying no events are lost during handler transitions
- [ ] Document the test patterns in src/docs/asciidoc/en/user-guide/10_using_the_disruptor.adoc
Create GitHub Action workflow for JMH microbenchmark performance regression detection
The repo has gradle/jmh.gradle and gradle/perf.gradle configured but no automated CI workflow (beyond manual jcstress tests in .github/workflows/). A JMH-based performance regression detection workflow would help catch performance regressions in PRs and protect the core value proposition of this high-performance library.
- [ ] Create .github/workflows/jmh-benchmark.yml workflow file
- [ ] Configure workflow to run JMH benchmarks on PR submissions and main branch
- [ ] Add baseline performance metrics storage/comparison (consider jmh-json-report action)
- [ ] Add workflow step to comment on PRs with performance deltas
- [ ] Document performance testing procedures in src/docs/asciidoc/en/developer-guide/20_performance_tests.adoc
Add integration tests for KeyedBatching example with multiple thread scenarios
KeyedBatching.java is a sophisticated example for batching events by key, but lacks dedicated test coverage in src/test. Given the complexity of multi-threaded key-based batching logic, comprehensive tests would validate correctness and provide documentation for advanced use cases.
- [ ] Create src/test/java/com/lmax/disruptor/examples/KeyedBatchingTest.java with JUnit 5
- [ ] Add tests for correct batching with single producer, multiple consumers
- [ ] Add tests for event ordering guarantees within each key batch
- [ ] Add tests for concurrent key producers and batch completion
- [ ] Add performance/stress tests using jcstress patterns from gradle/jcstress.gradle
- [ ] Update src/docs/asciidoc/en/user-guide/40_batch_rewind_use_case.adoc with KeyedBatching examples
🌿Good first issues
- Add JMH benchmark for WaitStrategy implementations: gradle/jmh.gradle is configured but there may be missing concrete benchmarks comparing BlockingWaitStrategy vs BusySpinWaitStrategy vs Phased variants under different load profiles—good way to learn performance testing and wait strategy tradeoffs.
- Expand user-guide documentation with a 'Common Pitfalls' section in src/docs/asciidoc/en/user-guide/30_known_issues.adoc—document real issues like object allocation inside event handlers, improper waitStrategy selection, and incorrect EventFactory usage, with runnable code examples.
- Add pre-commit hook validation in .githooks/pre-commit to auto-run checkstyle and JUnit quick-smoke tests before commit—the hook file exists but appears minimal; extending it to prevent style violations and obvious test failures would improve DX for contributors.
⭐Top contributors
Click to expand
Top contributors
- @Palmr — 61 commits
- @adacooke — 6 commits
- @swarren12 — 6 commits
- @nicholassm — 6 commits
- @grumpyjames — 5 commits
📝Recent commits
Click to expand
Recent commits
c871ca4— Merge pull request #495 from LMAX-Exchange/ci/java21 (adacooke)ddfad22— Update gradle to 8.10 (adacooke)73b7a41— Also run CI on Java 21 (adacooke)003ac13— Merge pull request #492 from Tombert/master (adacooke)b219713— Add @FunctionalInteface annotation for the eventhandlerbase (Tombert)7febcfd— Merge pull request #494 from LMAX-Exchange/bugfix/upload-artifact (grumpyjames)bf64803— Use unique build artifact names (adacooke)d02f6f2— Update upload-artifact to v4 (adacooke)86a848e— Fix footnote (swarren12)0a5adf2— Use upload-artifact v3 for now. (iziamos)
🔒Security observations
The LMAX Disruptor project demonstrates a solid security foundation with active CI/CD pipelines (CodeQL analysis, gradle-wrapper validation). The main repository contains no hardcoded secrets or obvious injection vulnerabilities based on the file structure analysis. However, several dependency versions are outdated, and no active dependency vulnerability scanning is configured. Recommendations include updating dependencies to latest versions, implementing OWASP Dependency-Check, conditionally disabling debug flags, and ensuring gradle-wrapper validation is enforced. The project follows industry best practices with Apache 2.0 licensing and professional build configuration.
- Medium · Outdated Checkstyle Dependency —
build.gradle - dependencies block. The project uses checkstyle version 10.4, which may contain known vulnerabilities. Checkstyle should be regularly updated to the latest version to ensure security patches are applied. Fix: Update checkstyle to the latest stable version (currently 10.12.x or later) and verify compatibility with the project. - Medium · Gradle Wrapper Security —
gradle/wrapper/gradle-wrapper.jar. The gradle-wrapper.jar is a binary file committed to version control. While gradle-wrapper-validation.yml workflow exists, ensure the wrapper is properly validated and from trusted sources. Fix: Ensure gradle-wrapper-validation.yml workflow is enabled and running. Regularly verify the wrapper checksum matches official Gradle releases. - Low · JUnit Jupiter Dependency Version —
build.gradle - testImplementation 'org.junit.jupiter:junit-jupiter:5.9.0'. JUnit Jupiter 5.9.0 is relatively old (released Sep 2022). Using outdated test dependencies may miss security fixes and improvements. Fix: Update JUnit Jupiter to the latest LTS version (5.9.x or 5.10.x series) to ensure security patches and bug fixes are included. - Low · Debug Flag Enabled in Production Build —
build.gradle - compileJava and compileTestJava blocks. The compileJava and compileTestJava tasks have options.debug = true, which may expose additional debugging information in compiled bytecode. Fix: Consider conditionally disabling debug flags for production/release builds. Use a property-based approach: options.debug = project.hasProperty('enableDebug') - Low · No OWASP Dependency Check Plugin —
build.gradle - plugins block. The build configuration does not include dependency vulnerability scanning tools (e.g., OWASP Dependency-Check or snyk). This limits visibility into known vulnerabilities in transitive dependencies. Fix: Add OWASP Dependency-Check plugin: id 'org.owasp.dependencycheck' version '8.4.2' and run regular scans in CI/CD pipeline. - Low · Hamcrest Dependency Age —
build.gradle - testImplementation 'org.hamcrest:hamcrest:2.2'. Hamcrest 2.2 is from 2020. While functional, newer versions may contain security improvements and bug fixes. Fix: Update to Hamcrest 2.2+ (latest is 2.1, verify latest available) to ensure compatibility and security updates.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.