From 39cae9c79a08b70839215fe1a73c74e73db2bfd5 Mon Sep 17 00:00:00 2001 From: Michael Panzlaff Date: Tue, 25 Aug 2026 12:25:43 +0200 Subject: [PATCH] Implement warmup delay for LIKWID collector --- collectors/likwidMetric.go | 39 +++++++++++++++++++++++++++++++++++++- collectors/likwidMetric.md | 1 + 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/collectors/likwidMetric.go b/collectors/likwidMetric.go index b647299..37fccbd 100644 --- a/collectors/likwidMetric.go +++ b/collectors/likwidMetric.go @@ -46,6 +46,7 @@ const ( LIKWID_LIB_DL_FLAGS = dl.RTLD_LAZY | dl.RTLD_GLOBAL LIKWID_DEF_ACCESSMODE = "direct" LIKWID_DEF_LOCKFILE = "/var/run/likwid.lock" + LIKWID_DEF_WARMUP_DEL = "0s" ) type LikwidCollectorMetricConfig struct { @@ -83,6 +84,7 @@ type LikwidCollectorConfig struct { DaemonPath string `json:"accessdaemon_path,omitempty"` LibraryPath string `json:"liblikwid_path,omitempty"` LockfilePath string `json:"lockfile_path,omitempty"` + WarmupDelay string `json:"warmup_delay"` } type LikwidCollector struct { @@ -104,6 +106,7 @@ type LikwidCollector struct { likwidGroups map[C.int]LikwidEventsetConfig lock sync.Mutex measureThread thread.Thread + warmupDelay time.Duration } type LikwidMetric struct { @@ -206,6 +209,7 @@ func (m *LikwidCollector) Init(config json.RawMessage) error { m.config.AccessMode = LIKWID_DEF_ACCESSMODE m.config.LibraryPath = LIKWID_LIB_NAME m.config.LockfilePath = LIKWID_DEF_LOCKFILE + m.config.WarmupDelay = LIKWID_DEF_WARMUP_DEL if len(config) > 0 { d := json.NewDecoder(bytes.NewReader(config)) d.DisallowUnknownFields() @@ -242,6 +246,17 @@ func (m *LikwidCollector) Init(config json.RawMessage) error { m.cpu2tid[c] = i } + if len(m.config.WarmupDelay) > 0 { + t, err := time.ParseDuration(m.config.WarmupDelay) + if err != nil { + return fmt.Errorf("%s Init(): Cannot parse WarmupDelay: %w", m.name, err) + } + if t < 0 { + return fmt.Errorf("%s Init(): WarmupDelay must not be negative", m.name) + } + m.warmupDelay = t + } + m.likwidGroups = make(map[C.int]LikwidEventsetConfig) // This is for the global metrics computation test @@ -495,6 +510,28 @@ func (m *LikwidCollector) takeMeasurement(evidx int, evset LikwidEventsetConfig, if ret != 0 { return true, fmt.Errorf("failed to start events '%s', error %d", evset.go_estr, ret) } + + // warmup measuring + if m.warmupDelay > 0 { + fmt.Printf("Performing warmup measurement for %s\n", m.warmupDelay) + select { + case <-sigchan: + ret = -1 + case e := <-watcher.Events: + if e.Op != fsnotify.Chmod { + ret = C.perfmon_readCounters() + } + default: + ret = C.perfmon_readCounters() + } + if ret != 0 { + return true, fmt.Errorf("failed to read events '%s', error %d", evset.go_estr, ret) + } + + time.Sleep(m.warmupDelay) + } + + // begin measuring select { case <-sigchan: ret = -1 @@ -512,7 +549,7 @@ func (m *LikwidCollector) takeMeasurement(evidx int, evset LikwidEventsetConfig, // Wait time.Sleep(interval) - // Read counters + // end measuring select { case <-sigchan: ret = -1 diff --git a/collectors/likwidMetric.md b/collectors/likwidMetric.md index ef435b2..6fcb9b6 100644 --- a/collectors/likwidMetric.md +++ b/collectors/likwidMetric.md @@ -63,6 +63,7 @@ Additional options: - `accessdaemon_path`: Folder of the accessDaemon `likwid-accessD` (like `/usr/local/sbin`) - `liblikwid_path`: Location of `liblikwid.so` including file name like `/usr/local/lib/liblikwid.so` - `lockfile_path`: Location of LIKWID's lock file if multiple tools should access the hardware counters. Default `/var/run/likwid.lock` +- `warmup_delay`: Run an additional measurement of the specified length before the actual measurement. This can be used as a workaround for CPU starvation (during high load) in the measurement thread. Default is disabled (i.e. `0s`). ### Available metric types