mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-09-24 17:04:30 +00:00
CP10-3 Tier 1 optimizations (T1-T4): - TCP_NODELAY + 256KB socket buffers on NVMe/TCP connections - Response batching: all C2H data chunks + CapsuleResp in single flush - Tiered buffer pool (4KB/64KB/256KB sync.Pool) for write payloads - Configurable MaxH2CDataLength wiring through controller/IC/chunking BUG-CP103-1: NVMe write retry with jittered backoff for transient WAL pressure - writeWithRetry() with bounded backoff [50/200/800ms] - throttleOnWALPressure() pre-write delay above 90% WAL usage - WALPressureProvider interface + NVMeAdapter.WALPressure() BUG-CP103-2: Volume-level WAL admission control - WALAdmission with counting semaphore (max concurrent writers) - Soft watermark (0.7): small delay to desynchronize herd - Hard watermark (0.9): block until flusher drains - Single-deadline budget shared across watermark wait + semaphore - Close-aware during both watermark and semaphore waits - Wired into BlockVol.WriteLBA() and Trim() Benchmark platform enhancements: - NVMe benchmark actions and scenarios (A/B, CW sweep, IOQ sweep) - Database benchmark actions (SQLite, pgbench) - K8s operator QA reconciler tests - New testrunner scenarios for HA, fault injection, CSI lifecycle Test counts: 213 NVMe + 625 engine + operator + testrunner tests, all passing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
48 lines
1.2 KiB
Go
48 lines
1.2 KiB
Go
package nvme
|
|
|
|
import "sync"
|
|
|
|
// bufPool provides tiered buffer pools for NVMe I/O.
|
|
// Three tiers: 4KB (small I/O), 64KB (medium), 256KB (large).
|
|
var bufPool = struct {
|
|
small sync.Pool // 4KB
|
|
medium sync.Pool // 64KB
|
|
large sync.Pool // 256KB
|
|
}{
|
|
small: sync.Pool{New: func() any { b := make([]byte, 4096); return &b }},
|
|
medium: sync.Pool{New: func() any { b := make([]byte, 65536); return &b }},
|
|
large: sync.Pool{New: func() any { b := make([]byte, 262144); return &b }},
|
|
}
|
|
|
|
// getBuffer returns a buffer of at least size bytes from the pool.
|
|
func getBuffer(size int) []byte {
|
|
switch {
|
|
case size <= 4096:
|
|
bp := bufPool.small.Get().(*[]byte)
|
|
return (*bp)[:size]
|
|
case size <= 65536:
|
|
bp := bufPool.medium.Get().(*[]byte)
|
|
return (*bp)[:size]
|
|
case size <= 262144:
|
|
bp := bufPool.large.Get().(*[]byte)
|
|
return (*bp)[:size]
|
|
default:
|
|
return make([]byte, size) // oversized: don't pool
|
|
}
|
|
}
|
|
|
|
// putBuffer returns a buffer to the appropriate pool.
|
|
func putBuffer(buf []byte) {
|
|
c := cap(buf)
|
|
buf = buf[:c]
|
|
switch c {
|
|
case 4096:
|
|
bufPool.small.Put(&buf)
|
|
case 65536:
|
|
bufPool.medium.Put(&buf)
|
|
case 262144:
|
|
bufPool.large.Put(&buf)
|
|
// Oversized or wrong-sized: let GC collect
|
|
}
|
|
}
|