fix: implement group commit collection window (500µs or 32KB)

Replace polling loop (Collect + Sleep) with proper batch collection:
- Block on first request via channel receive
- Start 500µs timer for collection window
- Accumulate requests until timer fires or batch reaches 32KB
- Shutdown handling at all blocking points

Design doc §3.2.5: '等待组提交触发(500µs 或 32KB,先到者触发)'

Add GroupCommitDelay config field (default 500µs, must be > 0 and < 10ms).
This commit is contained in:
dailz
2026-06-12 16:15:08 +08:00
parent 56bec62a6e
commit e34de4acc9
3 changed files with 96 additions and 15 deletions
+18 -6
View File
@@ -4,14 +4,14 @@ package config
import (
"fmt"
"math"
"time"
)
// WAL format constants derived from the binary layout specification.
const (
walFileHeaderSize uint64 = 32
walBlockSize uint32 = 32 * 1024 // 32KB
walFileHeaderSize uint64 = 32
physicalRecordHeaderSize uint64 = 7
walBatchHeaderSize uint64 = 18 // flags(2) + baseSequence(8) + entryCount(4) + entriesSize(4)
walBatchHeaderSize uint64 = 18 // flags(2) + baseSequence(8) + entryCount(4) + entriesSize(4)
)
// WalConfig holds configuration for the Write-Ahead Log subsystem.
@@ -38,6 +38,10 @@ type WalConfig struct {
// Default: 4MB.
MaxBatchSize uint32
// GroupCommitDelay is the maximum time to collect requests before writing a
// WAL group commit batch. Default: 500µs. Must be > 0 and < 10ms.
GroupCommitDelay time.Duration
// MaxKeyBytes is the maximum size of a single key in bytes.
// Default: 4KB.
MaxKeyBytes uint32
@@ -60,12 +64,13 @@ type WalConfig struct {
func Defaults() WalConfig {
return WalConfig{
MaxSegmentSize: 64 * 1024 * 1024, // 64MB
BlockSize: 32 * 1024, // 32KB
BlockSize: 32 * 1024, // 32KB
SyncMode: "always",
MaxBatchEntries: 10000,
MaxBatchSize: 4 * 1024 * 1024, // 4MB
MaxKeyBytes: 4 * 1024, // 4KB
MaxInlineValue: 4 * 1024, // 4KB
GroupCommitDelay: 500 * time.Microsecond,
MaxKeyBytes: 4 * 1024, // 4KB
MaxInlineValue: 4 * 1024, // 4KB
MemTableSize: 64 * 1024 * 1024, // 64MB
MaxImmutableCount: 3,
}
@@ -89,6 +94,9 @@ func (c *WalConfig) applyDefaults() {
if c.MaxBatchSize == 0 {
c.MaxBatchSize = d.MaxBatchSize
}
if c.GroupCommitDelay == 0 {
c.GroupCommitDelay = d.GroupCommitDelay
}
if c.MaxKeyBytes == 0 {
c.MaxKeyBytes = d.MaxKeyBytes
}
@@ -121,6 +129,10 @@ func (c *WalConfig) Validate() error {
return fmt.Errorf("config: MaxImmutableCount must be >= 1, got %d", c.MaxImmutableCount)
}
if c.GroupCommitDelay <= 0 || c.GroupCommitDelay >= 10*time.Millisecond {
return fmt.Errorf("config: GroupCommitDelay must be > 0 and < 10ms, got %s", c.GroupCommitDelay)
}
// --- Checked arithmetic invariant validation ---
// Mirrors the derivation in docs/design.md § WAL Segment Rotation.