mirror of
https://github.com/ClusterCockpit/cc-metric-collector.git
synced 2024-12-27 07:39:05 +01:00
Add Simultaneous Multithreading siblings
This commit is contained in:
parent
7246278745
commit
f3ffa29a37
@ -18,7 +18,8 @@ const SYSFS_CPUBASE = `/sys/devices/system/cpu`
|
||||
// Structure holding all information about a hardware thread
|
||||
type HwthreadEntry struct {
|
||||
CpuID int // CPU hardware threads
|
||||
SMT int // symmetric hyper threading ID
|
||||
SMT int // Simultaneous Multithreading ID
|
||||
ThreadSiblingsList []int // Simultaneous Multithreading siblings
|
||||
Core int // CPU core ID
|
||||
Socket int // CPU sockets (physical) ID
|
||||
Die int // CPU Die ID
|
||||
@ -36,30 +37,28 @@ var cache struct {
|
||||
CpuData []HwthreadEntry
|
||||
}
|
||||
|
||||
// fileToInt reads an integer value from a file
|
||||
// fileToInt reads an integer value from a sysfs file
|
||||
// In case of an error -1 is returned
|
||||
// Used internally for sysfs file reads
|
||||
func fileToInt(path string) int {
|
||||
buffer, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
cclogger.ComponentError("ccTopology", "Reading", path, ":", err.Error())
|
||||
cclogger.ComponentError("ccTopology", "fileToInt", "Reading", path, ":", err.Error())
|
||||
return -1
|
||||
}
|
||||
stringBuffer := strings.TrimSpace(string(buffer))
|
||||
id, err := strconv.Atoi(stringBuffer)
|
||||
if err != nil {
|
||||
cclogger.ComponentError("ccTopology", "Parsing", path, ":", stringBuffer, err.Error())
|
||||
cclogger.ComponentError("ccTopology", "fileToInt", "Parsing", path, ":", stringBuffer, err.Error())
|
||||
return -1
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// fileToList reads a list from a file
|
||||
// fileToList reads a list from a sysfs file
|
||||
// A list consists of value ranges separated by colon
|
||||
// A range can be a single value or a range of values given by a startValue-endValue
|
||||
// In case of an error nil is returned
|
||||
// Used internally for sysfs file reads
|
||||
func fileToList(path string) []int {
|
||||
// Read thread sibling list
|
||||
buffer, err := os.ReadFile(path)
|
||||
@ -78,23 +77,25 @@ func fileToList(path string) []int {
|
||||
case 1:
|
||||
singleValue, err := strconv.Atoi(valueRange[0])
|
||||
if err != nil {
|
||||
cclogger.ComponentError("CCTopology", "fileToList", err.Error())
|
||||
cclogger.ComponentError("CCTopology", "fileToList", "Parsing", valueRange[0], ":", err.Error())
|
||||
return nil
|
||||
}
|
||||
list = append(list, singleValue)
|
||||
case 2:
|
||||
startValue, err := strconv.Atoi(valueRange[0])
|
||||
if err != nil {
|
||||
cclogger.ComponentError("CCTopology", "fileToList", err.Error())
|
||||
cclogger.ComponentError("CCTopology", "fileToList", "Parsing", valueRange[0], ":", err.Error())
|
||||
return nil
|
||||
}
|
||||
endValue, err := strconv.Atoi(valueRange[1])
|
||||
if err != nil {
|
||||
cclogger.ComponentError("CCTopology", "fileToList", err.Error())
|
||||
cclogger.ComponentError("CCTopology", "fileToList", "Parsing", valueRange[1], ":", err.Error())
|
||||
return nil
|
||||
}
|
||||
for value := startValue; value <= endValue; value++ {
|
||||
list = append(list, value)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return list
|
||||
@ -149,19 +150,26 @@ func init() {
|
||||
// File globbing for NUMA node
|
||||
files, err := filepath.Glob(globPath)
|
||||
if err != nil {
|
||||
cclogger.ComponentError("CCTopology", "CpuData:getNumaDomain", err.Error())
|
||||
cclogger.ComponentError("CCTopology", "init:getNumaDomain", err.Error())
|
||||
return -1
|
||||
}
|
||||
|
||||
// Check, that exactly one NUMA domain was found
|
||||
if len(files) != 1 {
|
||||
cclogger.ComponentError("CCTopology", "init:getNumaDomain", "Number of NUMA domains != 1: ", len(files))
|
||||
return -1
|
||||
}
|
||||
|
||||
// Extract NUMA node ID
|
||||
matches := regex.FindStringSubmatch(files[0])
|
||||
if len(matches) != 2 {
|
||||
cclogger.ComponentError("CCTopology", "init:getNumaDomain", "Failed to extract NUMA node ID from: ", files[0])
|
||||
return -1
|
||||
}
|
||||
|
||||
id, err := strconv.Atoi(matches[1])
|
||||
if err != nil {
|
||||
cclogger.ComponentError("CCTopology", "init:getNumaDomain", "Failed to parse NUMA node ID from: ", matches[1])
|
||||
return -1
|
||||
}
|
||||
|
||||
@ -174,14 +182,11 @@ func init() {
|
||||
cache.DieList = make([]int, len(cache.HwthreadList))
|
||||
cache.SMTList = make([]int, len(cache.HwthreadList))
|
||||
cache.NumaDomainList = make([]int, len(cache.HwthreadList))
|
||||
cache.CpuData = make([]HwthreadEntry, len(cache.HwthreadList))
|
||||
for i, c := range cache.HwthreadList {
|
||||
// Set base directory for topology lookup
|
||||
base :=
|
||||
filepath.Join(
|
||||
SYSFS_CPUBASE,
|
||||
fmt.Sprintf("cpu%d", c),
|
||||
)
|
||||
topoBase := filepath.Join(base, "topology")
|
||||
// Set cpuBase directory for topology lookup
|
||||
cpuBase := filepath.Join(SYSFS_CPUBASE, fmt.Sprintf("cpu%d", c))
|
||||
topoBase := filepath.Join(cpuBase, "topology")
|
||||
|
||||
// Lookup Core ID
|
||||
cache.CoreList[i] = fileToInt(filepath.Join(topoBase, "core_id"))
|
||||
@ -196,14 +201,25 @@ func init() {
|
||||
}
|
||||
|
||||
// Lookup thread siblings list
|
||||
threadList := fileToList(filepath.Join(topoBase, "thread_siblings_list"))
|
||||
threadSiblingList := fileToList(filepath.Join(topoBase, "thread_siblings_list"))
|
||||
|
||||
// Find index of CPU ID in thread sibling list
|
||||
// if not found return -1
|
||||
cache.SMTList[i] = slices.Index(threadList, c)
|
||||
cache.SMTList[i] = slices.Index(threadSiblingList, c)
|
||||
|
||||
// Lookup NUMA domain id
|
||||
cache.NumaDomainList[i] = getNumaDomain(base)
|
||||
cache.NumaDomainList[i] = getNumaDomain(cpuBase)
|
||||
|
||||
cache.CpuData[i] =
|
||||
HwthreadEntry{
|
||||
CpuID: cache.HwthreadList[i],
|
||||
SMT: cache.SMTList[i],
|
||||
ThreadSiblingsList: threadSiblingList,
|
||||
Socket: cache.SocketList[i],
|
||||
NumaDomain: cache.NumaDomainList[i],
|
||||
Die: cache.DieList[i],
|
||||
Core: cache.CoreList[i],
|
||||
}
|
||||
}
|
||||
|
||||
cache.uniqHwthreadList = slices.Clone(cache.HwthreadList)
|
||||
@ -229,19 +245,6 @@ func init() {
|
||||
cache.uniqNumaDomainList = slices.Clone(cache.NumaDomainList)
|
||||
slices.Sort(cache.uniqNumaDomainList)
|
||||
cache.uniqNumaDomainList = slices.Compact(cache.uniqNumaDomainList)
|
||||
|
||||
cache.CpuData = make([]HwthreadEntry, len(cache.HwthreadList))
|
||||
for i := range cache.HwthreadList {
|
||||
cache.CpuData[i] =
|
||||
HwthreadEntry{
|
||||
CpuID: cache.HwthreadList[i],
|
||||
SMT: cache.SMTList[i],
|
||||
Socket: cache.SocketList[i],
|
||||
NumaDomain: cache.NumaDomainList[i],
|
||||
Die: cache.DieList[i],
|
||||
Core: cache.CoreList[i],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SocketList gets the list of CPU socket IDs
|
||||
@ -299,7 +302,12 @@ func GetTypeList(topology_type string) []int {
|
||||
|
||||
// CpuData returns CPU data for each hardware thread
|
||||
func CpuData() []HwthreadEntry {
|
||||
return slices.Clone(cache.CpuData)
|
||||
// return a deep copy to protect cache data
|
||||
c := slices.Clone(cache.CpuData)
|
||||
for i := range c {
|
||||
c[i].ThreadSiblingsList = slices.Clone(cache.CpuData[i].ThreadSiblingsList)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// Structure holding basic information about a CPU
|
||||
|
Loading…
Reference in New Issue
Block a user