From fdeb29bd40c258f820d3b2cd1d36a25cd9a14650 Mon Sep 17 00:00:00 2001 From: "Harper, Jason M" Date: Thu, 20 Nov 2025 11:35:41 -0800 Subject: [PATCH 1/3] fix: CHAs per socket value for metric formulas Signed-off-by: Harper, Jason M --- cmd/metrics/loader_util.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/metrics/loader_util.go b/cmd/metrics/loader_util.go index cfa77914..8ed2db09 100644 --- a/cmd/metrics/loader_util.go +++ b/cmd/metrics/loader_util.go @@ -166,7 +166,7 @@ func replaceConstants(metrics []MetricDefinition, metadata Metadata) ([]MetricDe return nil, fmt.Errorf("unknown granularity: %s", flagGranularity) } coresPerSocket := fmt.Sprintf("%f", float64(metadata.CoresPerSocket)) - chasPerSocket := fmt.Sprintf("%f", float64(len(metadata.UncoreDeviceIDs["cha"]))) + chasPerSocket := fmt.Sprintf("%f", float64(len(metadata.UncoreDeviceIDs["cha"]))/float64(metadata.SocketCount)) socketCount := fmt.Sprintf("%f", float64(metadata.SocketCount)) hyperThreadingOn := fmt.Sprintf("%t", metadata.ThreadsPerCore > 1) threadsPerCore := fmt.Sprintf("%f", float64(metadata.ThreadsPerCore)) From a0888b3648f773aab277a507a76127594320007b Mon Sep 17 00:00:00 2001 From: "Harper, Jason M" Date: Fri, 21 Nov 2025 11:06:04 -0800 Subject: [PATCH 2/3] revert as original was correct Signed-off-by: Harper, Jason M --- cmd/metrics/loader_util.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/metrics/loader_util.go b/cmd/metrics/loader_util.go index 8ed2db09..cfa77914 100644 --- a/cmd/metrics/loader_util.go +++ b/cmd/metrics/loader_util.go @@ -166,7 +166,7 @@ func replaceConstants(metrics []MetricDefinition, metadata Metadata) ([]MetricDe return nil, fmt.Errorf("unknown granularity: %s", flagGranularity) } coresPerSocket := fmt.Sprintf("%f", float64(metadata.CoresPerSocket)) - chasPerSocket := fmt.Sprintf("%f", float64(len(metadata.UncoreDeviceIDs["cha"]))/float64(metadata.SocketCount)) + chasPerSocket := fmt.Sprintf("%f", float64(len(metadata.UncoreDeviceIDs["cha"]))) socketCount := fmt.Sprintf("%f", float64(metadata.SocketCount)) hyperThreadingOn := fmt.Sprintf("%t", metadata.ThreadsPerCore > 1) threadsPerCore := fmt.Sprintf("%f", float64(metadata.ThreadsPerCore)) From c57332eac2a1802778ec71e6fb5d57fa68281210 Mon Sep 17 00:00:00 2001 From: "Harper, Jason M" Date: Fri, 21 Nov 2025 11:07:05 -0800 Subject: [PATCH 3/3] eliminate duplicate uncore events across groups as this causes perf to misreport event values Signed-off-by: Harper, Jason M --- cmd/metrics/loader_perfmon_group_uncore.go | 51 +++++++++++++++++----- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/cmd/metrics/loader_perfmon_group_uncore.go b/cmd/metrics/loader_perfmon_group_uncore.go index 38451ec5..1996befe 100644 --- a/cmd/metrics/loader_perfmon_group_uncore.go +++ b/cmd/metrics/loader_perfmon_group_uncore.go @@ -201,20 +201,49 @@ func (group UncoreGroup) StringForPerf() (string, error) { } func MergeUncoreGroups(uncoreGroups []UncoreGroup) ([]UncoreGroup, error) { - i := 0 - for i < len(uncoreGroups) { // this style of for loop is used to allow for removal of elements - j := i + 1 - for j < len(uncoreGroups) { // len(coreGroups) is recalculated on each iteration - tmpGroup := uncoreGroups[i].Copy() // Copy the group to avoid modifying the original - if err := tmpGroup.Merge(uncoreGroups[j]); err == nil { - uncoreGroups[i] = tmpGroup // Update the group at index i with the merged group - // remove the group at index j - uncoreGroups = append(uncoreGroups[:j], uncoreGroups[j+1:]...) + // First, eliminate duplicate events across groups (only needs to be done once) + seenEvents := make(map[string]int) // map of event name to group index where it first appears + for i := range uncoreGroups { + for j := range uncoreGroups[i].GeneralPurposeCounters { + event := uncoreGroups[i].GeneralPurposeCounters[j] + if event.IsEmpty() { + continue + } + + if firstGroupIdx, exists := seenEvents[event.EventName]; exists { + // Event already exists in another group, remove from current group + slog.Debug("removing duplicate uncore event from group", + slog.String("event", event.EventName), + slog.Int("firstGroup", firstGroupIdx), + slog.Int("currentGroup", i)) + uncoreGroups[i].GeneralPurposeCounters[j] = UncoreEvent{} } else { - j++ // Cannot merge these groups, try the next pair + // First time seeing this event, record it + seenEvents[event.EventName] = i } } - i++ + } + + // Then, keep merging until no more merges are possible + merged := true + for merged { + merged = false + i := 0 + for i < len(uncoreGroups) { + j := i + 1 + for j < len(uncoreGroups) { + tmpGroup := uncoreGroups[i].Copy() + if err := tmpGroup.Merge(uncoreGroups[j]); err == nil { + uncoreGroups[i] = tmpGroup + // remove the group at index j + uncoreGroups = append(uncoreGroups[:j], uncoreGroups[j+1:]...) + merged = true // mark that we made a change + } else { + j++ + } + } + i++ + } } return uncoreGroups, nil }