diff --git a/cmd/metrics/event_frame.go b/cmd/metrics/event_frame.go index b8dca3f0..5becff11 100644 --- a/cmd/metrics/event_frame.go +++ b/cmd/metrics/event_frame.go @@ -219,26 +219,37 @@ func coalesceEvents(allEvents []Event, scope string, granularity string, metadat // create a mapping of cpu numbers to event indices var cpuMap map[int]int - // if cpu range is specified, use it to determine the number of cpus - // otherwise, use the number of sockets, cores per socket, and threads per core - // to determine the number of cpus + // create a list of CPU IDs targeted for profiling + var cpuIDs []int + + // if CPU range is specified, use it to determine the number of CPUs + // otherwise, use the CPUSocketMap structure to determine the online CPUs + // then create a list of CPU IDs for the targeted CPUs if flagCpuRange != "" { - cpuList, err := util.SelectiveIntRangeToIntList(flagCpuRange) + var err error + cpuIDs, err = util.SelectiveIntRangeToIntList(flagCpuRange) if err != nil { return nil, fmt.Errorf("failed to parse cpu range: %w", err) } - numCPUs = len(cpuList) - cpuMap = make(map[int]int, numCPUs) - for i, cpu := range cpuList { - cpuMap[cpu] = i - } + numCPUs = len(cpuIDs) } else { - numCPUs = metadata.SocketCount * metadata.CoresPerSocket * metadata.ThreadsPerCore - cpuMap = make(map[int]int, numCPUs) - for i := 0; i < numCPUs; i++ { - cpuMap[i] = i + numCPUs = len(metadata.CPUSocketMap) + + for cpuID := range metadata.CPUSocketMap { + cpuIDs = append(cpuIDs, cpuID) } } + + // create a mapping of the target CPU IDs to their event indices + cpuMap = make(map[int]int, numCPUs) + + // sort the CPU IDs + slices.Sort(cpuIDs) + + // place the sorted CPU IDs into the mapping + for idx, cpuID := range cpuIDs { + cpuMap[cpuID] = idx + } // note: if some cores have been off-lined, this may cause an issue because 'perf' seems // to still report events for those cores newEvents := make([][]Event, numCPUs) diff --git a/cmd/metrics/metadata.go b/cmd/metrics/metadata.go index 5190475f..1fe3c466 100644 --- a/cmd/metrics/metadata.go +++ b/cmd/metrics/metadata.go @@ -85,7 +85,7 @@ func LoadMetadata(myTarget target.Target, noRoot bool, noSystemSummary bool, per metadata.ThreadsPerCore = 1 } // CPUSocketMap (from cpuInfo) - metadata.CPUSocketMap = createCPUSocketMap(metadata.CoresPerSocket, metadata.SocketCount, metadata.ThreadsPerCore == 2) + metadata.CPUSocketMap = createCPUSocketMap(cpuInfo) // Model Name (from cpuInfo) metadata.ModelName = cpuInfo[0]["model name"] // Vendor (from cpuInfo) @@ -709,29 +709,18 @@ func getKernelVersion(scriptOutputs map[string]script.ScriptOutput) (version str } // createCPUSocketMap creates a mapping of logical CPUs to their corresponding sockets. -// The function takes the number of cores per socket, the number of sockets, and a boolean indicating whether hyperthreading is enabled. +// The function traverses the output of /proc/cpuinfo and examines the "processor" and "physical id" fields. // It returns a map where the key is the logical CPU index and the value is the socket index. -func createCPUSocketMap(coresPerSocket int, sockets int, hyperthreading bool) (cpuSocketMap map[int]int) { +func createCPUSocketMap(cpuInfo []map[string]string) (cpuSocketMap map[int]int) { // Create an empty map cpuSocketMap = make(map[int]int) - // Calculate the total number of logical CPUs - totalCPUs := coresPerSocket * sockets - if hyperthreading { - totalCPUs *= 2 // hyperthreading doubles the number of logical CPUs - } - // Assign each CPU to a socket - for i := range totalCPUs { - // Assume that the CPUs are evenly distributed between the sockets - socket := i / coresPerSocket - if hyperthreading { - // With non-adjacent hyperthreading, the second logical CPU of each core is in the second half - if i >= totalCPUs/2 { - socket = (i - totalCPUs/2) / coresPerSocket - } - } - // Store the mapping - cpuSocketMap[i] = socket + // Iterate over the CPU info to create the mapping + for idx := range cpuInfo { + procID, _ := strconv.Atoi(cpuInfo[idx]["processor"]) + physID, _ := strconv.Atoi(cpuInfo[idx]["physical id"]) + cpuSocketMap[procID] = physID } + return cpuSocketMap }