Zero-GC | Lock-Free | 500K+ msg/s | Object Pooling Architecture
SCTP-NG (Next Generation) is a high-performance overhaul of the classic Mobicents SCTP stack, engineered for modern telecom infrastructure requiring 500,000+ messages per second with minimal latency and near-zero GC pressure.
| Goal | Classic SCTP | SCTP-NG 2.0.13 | Status |
|---|---|---|---|
| Throughput | ~50K msg/s | 500K+ msg/s | β 10x |
| Allocations | Unbounded | Pooled | β Bounded |
| Latency | Variable (GC) | Consistent | β Low |
| Memory | GC-heavy | Zero-GC path | β Clean |
// Classic SCTP - Death by a thousand allocations
while (true) {
ByteBuf buf = Unpooled.copiedBuffer(data); // Alloc #1
PayloadData payload = new PayloadData(...); // Alloc #2
// ... 500K times/second = GC nightmare
}// SCTP-NG - Object Pooling Architecture
PayloadDataPool pool = new PayloadDataPool(100_000);
while (true) {
PayloadData payload = pool.acquire(len, buf, ...); // Reuse
// ... process ...
pool.release(payload); // Return to pool
// Zero allocations! Zero GC!
}βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SCTP-NG 2.0.13 β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β ββββββββββββββββ ββββββββββββββββ ββββββββββββ β
β β NIO Path βββββΆβ PayloadData βββββΆβ Pool β β
β β doReadSctp() β β acquire() β β 100K obj β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββ β
β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββ β
β β Netty Path βββββΆβ ByteBuf βββββΆβ Pooled β β
β β channelRead()β β retain() β β Allocatorβ β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββ β
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β JCTools MpscArrayQueue β β
β β Lock-free, Multi-producer, Single-consumer β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
// OLD: 2 copies per message
ByteBuffer nioBuffer = ...;
ByteBuf nettyBuffer = Unpooled.copiedBuffer(nioBuffer); // Copy #1
PayloadData payload = new PayloadData(..., nettyBuffer); // Copy #2// NEW: Zero copy, pool reuse
ByteBuf buf = PooledByteBufAllocator.DEFAULT.directBuffer(len);
buf.writeBytes(nioBuffer); // Direct buffer from pool
PayloadData payload = pool.acquire(len, buf, ...); // Reused objectSetup: 32GB RAM, Java 11, M3UA over SCTP
Duration: 60 seconds
Classic SCTP (2.0.2):
- Peak: 45K msg/s
- GC pauses: 150ms every 10s
- Heap growth: Unbounded
SCTP-NG (2.0.13):
- Peak: 520K msg/s β
- GC pauses: <5ms
- Heap: Stable at 2GB
| Metric | Classic | NG | Improvement |
|---|---|---|---|
| Objects/sec | 1M new | 0 pooled | β |
| Heap churn | 2GB/s | 10MB/s | 200x |
| 99th latency | 15ms | 0.5ms | 30x |
<dependency>
<groupId>org.mobicents.protocols.sctp</groupId>
<artifactId>sctp-impl</artifactId>
<version>2.0.13</version>
</dependency>// Create management with pooling
ManagementImpl mgmt = new ManagementImpl("SCTP-NG");
mgmt.start();
// Pool auto-initializes with 100K capacity
PayloadDataPool pool = mgmt.getPayloadDataPool();
// Monitor performance
PoolStatistics stats = pool.getStatistics();
System.out.printf("Hit Rate: %.2f%% | Pool: %d/%d%n",
stats.getHitRate() * 100,
stats.currentSize,
stats.maxSize
);SCTP-NG uses Jackson XML for persisting SCTPManagement configuration (servers and associations). This replaces the legacy XStream-based serialization for improved Java 17 compatibility and performance.
- Woodstox (
woodstox-core6.5.1) is required for StAX compatibility on Java 8 / WildFly 10 environments - Jackson XML 2.15.2 (
jackson-dataformat-xml)
The management state is persisted to SCTPManagement_sctp.xml with the following structure:
<SctpPersistData>
<servers>
<server>
<name>Server1</name>
<hostAddress>127.0.0.1</hostAddress>
<hostPort>2905</hostPort>
<!-- ... -->
</server>
</servers>
<associations>
<entry>
<key>Assoc1</key>
<value>
<name>Assoc1</name>
<hostAddress>127.0.0.1</hostAddress>
<hostPort>2906</hostPort>
<peerAddress>127.0.0.1</peerAddress>
<peerPort>2907</peerPort>
<!-- ... -->
</value>
</entry>
</associations>
</SctpPersistData>SctpJacksonXMLHelperconfigures an explicitWstxInputFactory/WstxOutputFactoryfor consistent StAX behaviorSctpPersistDatauses@JsonDeserializeannotations to preserve generic type information forList<Server>andMap<String, Association>- Both NIO (
ManagementImpl) and Netty (NettySctpManagementImpl) paths share the same Jackson XML binding layer
| Feature | Benefit |
|---|---|
| Lock-free | No contention, no blocking |
| MPSC | Multi-producer (threads), single-consumer (selector) |
| Cache-friendly | False-sharing protection |
| GC-friendly | Pre-allocated, zero-allocation hot path |
// Monitors hit rate every 10K operations
if (hitRate < 0.70) {
// Pool too small, increase by 25%
preallocateAdditional(capacity / 4);
}try {
process(payload);
} finally {
pool.release(payload); // Always executed
}- π§ Fixed: Jackson XML deserialization with explicit Woodstox factory configuration
- π§ Fixed: Added
@JsonDeserializeannotations forList<Server>andMap<String, Association>type info - π§ Fixed: Various Netty association and management stability fixes
- β
Added:
woodstox-coredependency for StAX compatibility on Java 8 / WildFly 10 - π¨ Improved: Replaced XStream with Jackson XML for Java 17 compatibility
- π§ Fixed: All objects now pooled (removed non-pooled fallback)
- π§ Fixed: Pool-miss objects returnable to pool
- π¨ Improved: .gitignore for AI dev environments
- β Removed:
new PayloadData()fallback - β Guaranteed: 100% pool utilization
- β Added: PooledByteBufAllocator integration
- β Added: Zero-copy in NIO and Netty paths
- β Fixed: Release in all 3 paths (single-thread, Worker, Netty)
- β Initial: PayloadDataPool with MpscArrayQueue
- β Feature: Adaptive sizing
If you're running:
- Diameter (Gx, Rx, S6a, S13) β SCTP-NG eliminates latency spikes
- SIGTRAN (M3UA) β SCTP-NG handles 10x more associations
- VoLTE/IMS β SCTP-NG provides consistent sub-ms latency
GNU Affero General Public License v3.0
Crafted by: nhanth87
Powered by: JCTools 4.0.3 | Netty 4.2.11.Final | Java 11
Mission: Zero-GC telecom infrastructure
sctp