summaryrefslogtreecommitdiff
path: root/internal/stats/patterns.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-07-10 08:36:23 +0300
committerPaul Buetow <paul@buetow.org>2025-07-10 08:36:23 +0300
commit34e9665b837abd718b2da5c5fbedd47d9af0d201 (patch)
tree204ed27571c1bba3d51e3e2b442a6952de3f124a /internal/stats/patterns.go
parentd6bb3c0567ba8bfd2edd6c0d4541d8e191f7aa0e (diff)
Add comprehensive eventloop tests for multiple syscall types
- Add helper functions for FdEvent, PathEvent, and RetEvent types - Implement test cases for read, write, close, and mkdir syscalls - Test proper event pairing and file object creation - Validate syscall-specific behavior for different event types This expands test coverage beyond just openat syscalls to include file descriptor operations and path-based operations, providing a foundation for testing all supported syscall types. 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
Diffstat (limited to 'internal/stats/patterns.go')
-rw-r--r--internal/stats/patterns.go142
1 files changed, 142 insertions, 0 deletions
diff --git a/internal/stats/patterns.go b/internal/stats/patterns.go
new file mode 100644
index 0000000..06e906f
--- /dev/null
+++ b/internal/stats/patterns.go
@@ -0,0 +1,142 @@
+package stats
+
+import (
+ "math"
+ "time"
+)
+
+// PatternAnalysis represents the analysis of I/O patterns
+type PatternAnalysis struct {
+ // Burst detection
+ BurstCount int
+ BurstDuration time.Duration
+ BurstThreshold int64
+
+ // Periodicity detection
+ IsPeriodic bool
+ PeriodDuration time.Duration
+
+ // Trend analysis
+ TrendSlope float64
+ TrendDirection string // "increasing", "decreasing", "stable"
+}
+
+// AnalyzePatterns analyzes the I/O patterns from the statistics
+func (s *IOStats) AnalyzePatterns() *PatternAnalysis {
+ s.mu.RLock()
+ defer s.mu.RUnlock()
+
+ analysis := &PatternAnalysis{
+ BurstThreshold: 1000, // Configurable threshold
+ }
+
+ // Analyze bursts
+ analysis.analyzeBursts(s.bytesHistory, s.timestamps)
+
+ // Analyze periodicity
+ analysis.analyzePeriodicity(s.bytesHistory, s.timestamps)
+
+ // Analyze trends
+ analysis.analyzeTrend(s.bytesHistory, s.timestamps)
+
+ return analysis
+}
+
+func (a *PatternAnalysis) analyzeBursts(bytes []int64, timestamps []time.Time) {
+ if len(bytes) < 2 {
+ return
+ }
+
+ var currentBurstSize int64
+ var burstStart time.Time
+ inBurst := false
+
+ for i := 0; i < len(bytes); i++ {
+ if bytes[i] > a.BurstThreshold {
+ if !inBurst {
+ burstStart = timestamps[i]
+ inBurst = true
+ }
+ currentBurstSize += bytes[i]
+ } else if inBurst {
+ a.BurstCount++
+ a.BurstDuration += timestamps[i].Sub(burstStart)
+ inBurst = false
+ currentBurstSize = 0
+ }
+ }
+}
+
+func (a *PatternAnalysis) analyzePeriodicity(bytes []int64, timestamps []time.Time) {
+ if len(bytes) < 4 {
+ return
+ }
+
+ // Simple periodicity detection using autocorrelation
+ mean := 0.0
+ for _, b := range bytes {
+ mean += float64(b)
+ }
+ mean /= float64(len(bytes))
+
+ var maxCorrelation float64
+ var bestPeriod int
+
+ // Check for periods up to half the data length
+ for period := 1; period < len(bytes)/2; period++ {
+ correlation := 0.0
+ count := 0
+
+ for i := 0; i < len(bytes)-period; i++ {
+ correlation += (float64(bytes[i]) - mean) * (float64(bytes[i+period]) - mean)
+ count++
+ }
+
+ if count > 0 {
+ correlation /= float64(count)
+ if correlation > maxCorrelation {
+ maxCorrelation = correlation
+ bestPeriod = period
+ }
+ }
+ }
+
+ // If we found a strong correlation, consider it periodic
+ if maxCorrelation > 0.7 { // Threshold for periodicity
+ a.IsPeriodic = true
+ if bestPeriod > 0 && bestPeriod < len(timestamps)-1 {
+ a.PeriodDuration = timestamps[bestPeriod].Sub(timestamps[0])
+ }
+ }
+}
+
+func (a *PatternAnalysis) analyzeTrend(bytes []int64, timestamps []time.Time) {
+ if len(bytes) < 2 {
+ return
+ }
+
+ // Simple linear regression
+ var sumX, sumY, sumXY, sumX2 float64
+ n := float64(len(bytes))
+
+ for i := 0; i < len(bytes); i++ {
+ x := float64(timestamps[i].UnixNano())
+ y := float64(bytes[i])
+ sumX += x
+ sumY += y
+ sumXY += x * y
+ sumX2 += x * x
+ }
+
+ // Calculate slope
+ a.TrendSlope = (n*sumXY - sumX*sumY) / (n*sumX2 - sumX*sumX)
+
+ // Determine trend direction
+ if math.Abs(a.TrendSlope) < 0.1 {
+ a.TrendDirection = "stable"
+ } else if a.TrendSlope > 0 {
+ a.TrendDirection = "increasing"
+ } else {
+ a.TrendDirection = "decreasing"
+ }
+}