Packet Pools
- Packet PoolsPool Types OverviewPool TypeData MemoryDescriptor MemoryUse CaseScoped Packet Pool (Zero-Copy)
PoolSettings settings = new PoolSettings() .minCapacity(1000) .maxCapacity(10000); // One-liner FreeListPool<Packet> scopedPool = new FreeListPool<>(settings, Packet::ofScoped);Capture Loopwhile (capturing) { Packet packet = scopedPool.allocate(); // Bind to native packet data (zero-copy) packet.memory().bind(nativeDataSegment, dataOffset, dataLength); packet.descriptor().memory().bind(nativeDescSegment, descOffset, descLength); // Process - direct access to native memory processPacket(packet); // Unbind and recycle packet.memory().unbind(); packet.descriptor().memory().unbind(); packet.recycle(); }Bucketed Fixed Packet Pool (Variable Sizes)long[] packetSizes = {64, 1518, 9000, 16384, 65536}; PoolSettings settings = new PoolSettings() .minCapacity(100) .maxCapacity(1000); // One-liner - Packet::ofFixed matches BucketFactory signature perfectly BucketPool<Packet> bucketPool = new BucketPool<>(settings, packetSizes, Packet::ofFixed);Capture Loopwhile (capturing) { int packetSize = getPacketSize(nativePacket); // Allocate from smallest fitting bucket Packet packet = bucketPool.allocate(packetSize); if (packet == null) continue; // Copy data packet.memory().segment().copyFrom(nativeData, 0, packetSize); // Process processPacket(packet); // Recycle - returns to correct bucket automatically packet.recycle(); }Bucket MetricsPoolMetrics metrics = bucketPool.metrics(); System.out.printf("Total: %d allocations%n", metrics.allocations()); for (int i = 0; i < metrics.bucketCount(); i++) { System.out.printf("Bucket[%d] %d bytes: %d allocs%n", i, metrics.bucketSize(i), metrics.allocations(i)); }Hybrid Packet Pool (Scoped Data + Fixed Descriptor)PoolSettings settings = new PoolSettings() .minCapacity(1000) .maxCapacity(10000); // One-liner - descriptor allocated from Arena.ofShared() FreeListPool<Packet> hybridPool = new FreeListPool<>(settings, Packet::ofHybrid);Capture Loopwhile (capturing) { Packet packet = hybridPool.allocate(); // Bind data to native (zero-copy) packet.memory().bind(nativeDataSegment, dataOffset, dataLength); // Convert native descriptor to our format (into fixed memory) convertDescriptor(nativeDescriptor, packet.descriptor()); // Process processPacket(packet); // Unbind data only (descriptor stays in fixed memory) packet.memory().unbind(); packet.recycle(); }Summary: Pool Creation One-Liners// Scoped - zero-copy capture var scopedPool = new FreeListPool<>(settings, Packet::ofScoped); // Bucketed - variable size copy var bucketPool = new BucketPool<>(settings, sizes, Packet::ofFixed); // Hybrid - zero-copy data + fixed descriptor var hybridPool = new FreeListPool<>(settings, Packet::ofHybrid);Complete Examplepublic class PacketProcessingExample { public static void main(String[] args) { // === Scoped Pool (Zero-Copy) === var scopedPool = new FreeListPool<Packet>( new PoolSettings().capacity(10000), Packet::ofScoped ); // === Bucketed Pool (Variable Sizes) === var bucketPool = new BucketPool<Packet>( new PoolSettings().minCapacity(100).maxCapacity(1000), new long[]{64, 1518, 9000, 65536}, Packet::ofFixed ); // === Hybrid Pool (Scoped Data + Fixed Descriptor) === var hybridPool = new FreeListPool<Packet>( new PoolSettings().capacity(10000), Packet::ofHybrid ); // Use appropriate pool processWithPool(scopedPool); // Cleanup scopedPool.close(); bucketPool.close(); hybridPool.close(); } }Performance Tips
Last updated