Files
Steve Simpson 43a246f431 Alerting: Improve performance of /api/prometheus for large numbers of alerts. (#89268)
* Alerting: Optimize sorting alert instances.

* Also change other Labels fields for consistency
2024-06-17 12:25:47 +02:00

89 lines
2.2 KiB
Go

package definitions
import (
"flag"
"fmt"
"math/rand"
"testing"
)
var topkStrategy = flag.String("topk", "heap", "topk strategy to benchmark. choices: sort, heap")
var showComparisons = flag.Bool("show-comparisons", false, "whether to show the number of comparisons made")
func makeAlerts(amount int) []Alert {
// A typical distribution of alert states is that most are Normal
// and a few are Alerting, so we assume 99% Normal and 1% Alerting.
percentAlerting := 1
// Series will commonly have many labels.
numLabels := 10
alerts := make([]Alert, amount)
for i := 0; i < len(alerts); i++ {
lbls := make(map[string]string)
for label := 0; label < numLabels; label++ {
lbls[fmt.Sprintf("label_%d", label)] = fmt.Sprintf("label_%d_value_%d", label, i%100)
}
alerts[i].Labels = LabelsFromMap(lbls)
if i%100 < percentAlerting {
alerts[i].State = "alerting"
// Should populate ActiveAt because this prevents needing label comparison
} else {
alerts[i].State = "normal"
}
}
// Shuffle in a repeatable order to avoid any bias from the initial ordering.
r := rand.New(rand.NewSource(1))
r.Shuffle(len(alerts), func(i, j int) { alerts[i], alerts[j] = alerts[j], alerts[i] })
return alerts
}
func BenchmarkSortAlertsByImportance(b *testing.B) {
var topkFunc func(AlertsBy, []Alert, int)
switch *topkStrategy {
case "sort":
topkFunc = func(by AlertsBy, alerts []Alert, limit int) {
by.Sort(alerts)
if len(alerts) > limit {
_ = alerts[0:limit]
}
}
case "heap":
topkFunc = func(by AlertsBy, alerts []Alert, limit int) {
_ = by.TopK(alerts, limit)
}
}
for _, n := range []int{1000, 10000, 100000} {
for _, k := range []int{16, 100, 1000, 100000} {
b.Run(fmt.Sprintf("n_%d_k_%d", n, k), func(b *testing.B) {
b.StopTimer()
for bi := 0; bi < b.N; bi++ {
alerts := makeAlerts(n)
comparisons := 0
by := func(a1, a2 *Alert) bool {
comparisons++
return AlertsByImportance(a1, a2)
}
b.StartTimer()
topkFunc(by, alerts, k)
b.StopTimer()
if *showComparisons {
fmt.Printf("Number of comparisons (strategy: %s): %d\n", *topkStrategy, comparisons)
}
}
})
}
}
}