Remove plans/ directory (P0/P1/P2 work complete)
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
package adaptive
|
||||
|
||||
// Package adaptive: experimental / not yet active after P1-04 prune.
|
||||
// Retained for potential P2 integration. Not used at runtime (pruned from steamcache).
|
||||
// Package adaptive: experimental workload analyzer and adaptive cache manager.
|
||||
// Not active at runtime (pruned from the main request path in earlier hardening work).
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -40,6 +40,7 @@ type WorkloadAnalyzer struct {
|
||||
analysisInterval time.Duration
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
// AccessInfo tracks access patterns for individual files
|
||||
@@ -74,6 +75,7 @@ func NewWorkloadAnalyzer(analysisInterval time.Duration) *WorkloadAnalyzer {
|
||||
cancel: cancel,
|
||||
}
|
||||
|
||||
analyzer.wg.Add(1)
|
||||
// Start background analysis with much longer interval to reduce overhead
|
||||
go analyzer.analyzePatterns()
|
||||
|
||||
@@ -120,6 +122,7 @@ func (wa *WorkloadAnalyzer) RecordAccess(key string, size int64) {
|
||||
|
||||
// analyzePatterns analyzes access patterns in the background
|
||||
func (wa *WorkloadAnalyzer) analyzePatterns() {
|
||||
defer wa.wg.Done()
|
||||
ticker := time.NewTicker(wa.analysisInterval)
|
||||
defer ticker.Stop()
|
||||
|
||||
@@ -218,6 +221,7 @@ func (wa *WorkloadAnalyzer) GetAccessInfo(key string) *AccessInfo {
|
||||
// Stop stops the workload analyzer
|
||||
func (wa *WorkloadAnalyzer) Stop() {
|
||||
wa.cancel()
|
||||
wa.wg.Wait()
|
||||
}
|
||||
|
||||
// NewAdaptiveCacheManager creates a new adaptive cache manager
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package adaptive
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestWorkloadAnalyzer_Basic(t *testing.T) {
|
||||
t.Parallel()
|
||||
wa := NewWorkloadAnalyzer(100 * time.Millisecond)
|
||||
wa.RecordAccess("steam/depot/1", 1024)
|
||||
wa.RecordAccess("steam/depot/2", 2048)
|
||||
_ = wa.GetDominantPattern()
|
||||
if info := wa.GetAccessInfo("steam/depot/1"); info != nil {
|
||||
_ = info.AccessCount
|
||||
}
|
||||
wa.Stop()
|
||||
}
|
||||
|
||||
func TestAdaptiveCacheManager_Basic(t *testing.T) {
|
||||
t.Parallel()
|
||||
acm := NewAdaptiveCacheManager(50 * time.Millisecond)
|
||||
acm.RecordAccess("k", 100)
|
||||
_ = acm.GetCurrentStrategy()
|
||||
_ = acm.GetAdaptationCount()
|
||||
acm.Stop()
|
||||
}
|
||||
|
||||
// TestAdaptiveAnalyzer_UnderLoad + concurrent Record (improves 0% paths for analyzer goroutine per issue11).
|
||||
func TestAdaptiveAnalyzer_UnderLoad(t *testing.T) {
|
||||
t.Parallel()
|
||||
wa := NewWorkloadAnalyzer(20 * time.Millisecond)
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < 4; i++ {
|
||||
wg.Add(1)
|
||||
go func(id int) {
|
||||
defer wg.Done()
|
||||
for j := 0; j < 30; j++ {
|
||||
wa.RecordAccess("p"+string(rune('0'+id)), int64(j*100))
|
||||
}
|
||||
}(i)
|
||||
}
|
||||
wg.Wait()
|
||||
_ = wa.GetDominantPattern()
|
||||
wa.Stop()
|
||||
}
|
||||
Reference in New Issue
Block a user