summaryrefslogtreecommitdiff
path: root/internal/statsengine/process.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/statsengine/process.go')
-rw-r--r--internal/statsengine/process.go63
1 files changed, 61 insertions, 2 deletions
diff --git a/internal/statsengine/process.go b/internal/statsengine/process.go
index a0d29c1..e677744 100644
--- a/internal/statsengine/process.go
+++ b/internal/statsengine/process.go
@@ -6,8 +6,12 @@ import (
"time"
)
+const processRankTopNDefault = 20
+
type processAccumulator struct {
- byPID map[uint32]*processStats
+ topN int
+ maxSeen int
+ byPID map[uint32]*processStats
}
type processStats struct {
@@ -27,7 +31,28 @@ type processSnapshotInput struct {
}
func newProcessAccumulator() *processAccumulator {
- return &processAccumulator{byPID: make(map[uint32]*processStats)}
+ return newProcessAccumulatorWithConfig(processRankTopNDefault)
+}
+
+func newProcessAccumulatorWithConfig(topN int) *processAccumulator {
+ if topN <= 0 {
+ topN = processRankTopNDefault
+ }
+ return newProcessAccumulatorWithLimits(topN, topN*32)
+}
+
+func newProcessAccumulatorWithLimits(topN int, maxSeen int) *processAccumulator {
+ if topN <= 0 {
+ topN = processRankTopNDefault
+ }
+ if maxSeen < topN {
+ maxSeen = topN
+ }
+ return &processAccumulator{
+ topN: topN,
+ maxSeen: maxSeen,
+ byPID: make(map[uint32]*processStats),
+ }
}
func (a *processAccumulator) Add(pair *event.Pair) {
@@ -54,6 +79,7 @@ func (a *processAccumulator) Add(pair *event.Pair) {
if pair.Comm != "" {
stats.comm = pair.Comm
}
+ a.compactIfNeeded()
}
func (a *processAccumulator) Snapshot(elapsed time.Duration) []ProcessSnapshot {
@@ -100,6 +126,39 @@ func buildProcessSnapshots(inputs []processSnapshotInput, elapsed time.Duration)
return result
}
+func (a *processAccumulator) compactIfNeeded() {
+ if len(a.byPID) <= a.maxSeen {
+ return
+ }
+
+ ordered := make([]*processStats, 0, len(a.byPID))
+ for _, stats := range a.byPID {
+ ordered = append(ordered, stats)
+ }
+ sort.Slice(ordered, func(i, j int) bool {
+ return betterProcessRank(ordered[i], ordered[j])
+ })
+ if len(ordered) > a.topN {
+ ordered = ordered[:a.topN]
+ }
+
+ kept := make(map[uint32]*processStats, len(ordered))
+ for _, stats := range ordered {
+ kept[stats.pid] = stats
+ }
+ a.byPID = kept
+}
+
+func betterProcessRank(a, b *processStats) bool {
+ if a.count != b.count {
+ return a.count > b.count
+ }
+ if a.totalBytes != b.totalBytes {
+ return a.totalBytes > b.totalBytes
+ }
+ return a.pid < b.pid
+}
+
func (s processSnapshotInput) toSnapshot(rateDiv float64) ProcessSnapshot {
avg := 0.0
if s.count > 0 {