Completly avoid memory allocations in infinibandMetric read()

This commit is contained in:
Holger Obermaier 2023-08-21 10:09:09 +02:00
parent fc19b2b9a5
commit 1b97953cdb

View File

@ -18,18 +18,22 @@ import (
const IB_BASEPATH = "/sys/class/infiniband/" const IB_BASEPATH = "/sys/class/infiniband/"
type InfinibandCollectorMetric struct { type InfinibandCollectorMetric struct {
name string
path string path string
unit string unit string
scale int64 scale int64
addToIBTotal bool
addToIBTotalPkgs bool
currentState int64
lastState int64
} }
type InfinibandCollectorInfo struct { type InfinibandCollectorInfo struct {
LID string // IB local Identifier (LID) LID string // IB local Identifier (LID)
device string // IB device device string // IB device
port string // IB device port port string // IB device port
portCounterFiles map[string]InfinibandCollectorMetric // mapping counter name -> InfinibandCollectorMetric portCounterFiles []InfinibandCollectorMetric // mapping counter name -> InfinibandCollectorMetric
tagSet map[string]string // corresponding tag list tagSet map[string]string // corresponding tag list
lastState map[string]int64 // State from last measurement
} }
type InfinibandCollector struct { type InfinibandCollector struct {
@ -40,7 +44,7 @@ type InfinibandCollector struct {
SendTotalValues bool `json:"send_total_values"` // Send computed total values SendTotalValues bool `json:"send_total_values"` // Send computed total values
SendDerivedValues bool `json:"send_derived_values"` // Send derived values e.g. rates SendDerivedValues bool `json:"send_derived_values"` // Send derived values e.g. rates
} }
info []*InfinibandCollectorInfo info []InfinibandCollectorInfo
lastTimestamp time.Time // Store time stamp of last tick to derive bandwidths lastTimestamp time.Time // Store time stamp of last tick to derive bandwidths
} }
@ -113,11 +117,39 @@ func (m *InfinibandCollector) Init(config json.RawMessage) error {
// Check access to counter files // Check access to counter files
countersDir := filepath.Join(path, "counters") countersDir := filepath.Join(path, "counters")
portCounterFiles := map[string]InfinibandCollectorMetric{ portCounterFiles := []InfinibandCollectorMetric{
"ib_recv": {path: filepath.Join(countersDir, "port_rcv_data"), unit: "bytes", scale: 4}, {
"ib_xmit": {path: filepath.Join(countersDir, "port_xmit_data"), unit: "bytes", scale: 4}, name: "ib_recv",
"ib_recv_pkts": {path: filepath.Join(countersDir, "port_rcv_packets"), unit: "packets", scale: 1}, path: filepath.Join(countersDir, "port_rcv_data"),
"ib_xmit_pkts": {path: filepath.Join(countersDir, "port_xmit_packets"), unit: "packets", scale: 1}, unit: "bytes",
scale: 4,
addToIBTotal: true,
lastState: -1,
},
{
name: "ib_xmit",
path: filepath.Join(countersDir, "port_xmit_data"),
unit: "bytes",
scale: 4,
addToIBTotal: true,
lastState: -1,
},
{
name: "ib_recv_pkts",
path: filepath.Join(countersDir, "port_rcv_packets"),
unit: "packets",
scale: 1,
addToIBTotalPkgs: true,
lastState: -1,
},
{
name: "ib_xmit_pkts",
path: filepath.Join(countersDir, "port_xmit_packets"),
unit: "packets",
scale: 1,
addToIBTotalPkgs: true,
lastState: -1,
},
} }
for _, counter := range portCounterFiles { for _, counter := range portCounterFiles {
err := unix.Access(counter.path, unix.R_OK) err := unix.Access(counter.path, unix.R_OK)
@ -126,14 +158,8 @@ func (m *InfinibandCollector) Init(config json.RawMessage) error {
} }
} }
// Initialize last state
lastState := make(map[string]int64)
for counter := range portCounterFiles {
lastState[counter] = -1
}
m.info = append(m.info, m.info = append(m.info,
&InfinibandCollectorInfo{ InfinibandCollectorInfo{
LID: LID, LID: LID,
device: device, device: device,
port: port, port: port,
@ -144,7 +170,6 @@ func (m *InfinibandCollector) Init(config json.RawMessage) error {
"port": port, "port": port,
"lid": LID, "lid": LID,
}, },
lastState: lastState,
}) })
} }
@ -171,11 +196,12 @@ func (m *InfinibandCollector) Read(interval time.Duration, output chan lp.CCMetr
// Save current timestamp // Save current timestamp
m.lastTimestamp = now m.lastTimestamp = now
for _, info := range m.info { for i := range m.info {
info := &m.info[i]
currentState := make(map[string]int64) var ib_total, ib_total_pkts int64
for i := range info.portCounterFiles {
for counterName, counterDef := range info.portCounterFiles { counterDef := &info.portCounterFiles[i]
// Read counter file // Read counter file
line, err := os.ReadFile(counterDef.path) line, err := os.ReadFile(counterDef.path)
@ -192,15 +218,26 @@ func (m *InfinibandCollector) Read(interval time.Duration, output chan lp.CCMetr
if err != nil { if err != nil {
cclog.ComponentError( cclog.ComponentError(
m.name, m.name,
fmt.Sprintf("Read(): Failed to convert Infininiband metrice %s='%s' to int64: %v", counterName, data, err)) fmt.Sprintf("Read(): Failed to convert Infininiband metrice %s='%s' to int64: %v", counterDef.name, data, err))
continue continue
} }
// Scale raw value // Scale raw value
v *= counterDef.scale v *= counterDef.scale
// Save current state
counterDef.currentState = v
// Send absolut values // Send absolut values
if m.config.SendAbsoluteValues { if m.config.SendAbsoluteValues {
if y, err := lp.New(counterName, info.tagSet, m.meta, map[string]interface{}{"value": v}, now); err == nil { if y, err :=
lp.New(
counterDef.name,
info.tagSet,
m.meta,
map[string]interface{}{
"value": counterDef.currentState,
},
now); err == nil {
y.AddMeta("unit", counterDef.unit) y.AddMeta("unit", counterDef.unit)
output <- y output <- y
} }
@ -208,52 +245,58 @@ func (m *InfinibandCollector) Read(interval time.Duration, output chan lp.CCMetr
// Send derived values // Send derived values
if m.config.SendDerivedValues { if m.config.SendDerivedValues {
if info.lastState[counterName] >= 0 { if counterDef.lastState >= 0 {
rate := float64((v - info.lastState[counterName])) / timeDiff rate := float64((counterDef.currentState - counterDef.lastState)) / timeDiff
if y, err := lp.New(counterName+"_bw", info.tagSet, m.meta, map[string]interface{}{"value": rate}, now); err == nil { if y, err :=
lp.New(
counterDef.name+"_bw",
info.tagSet,
m.meta,
map[string]interface{}{
"value": rate,
},
now); err == nil {
y.AddMeta("unit", counterDef.unit+"/sec") y.AddMeta("unit", counterDef.unit+"/sec")
output <- y output <- y
}
}
counterDef.lastState = counterDef.currentState
}
// Sum up total values
if m.config.SendTotalValues {
switch {
case counterDef.addToIBTotal:
ib_total += counterDef.currentState
case counterDef.addToIBTotalPkgs:
ib_total_pkts += counterDef.currentState
} }
} }
} }
// Save current state // Send total values
currentState[counterName] = v if m.config.SendTotalValues {
}
// Save current state for use as last state
if m.config.SendDerivedValues {
info.lastState = currentState
}
if m.config.SendAbsoluteValues {
recv, recv_ok := currentState["ib_recv"]
xmit, xmit_ok := currentState["ib_xmit"]
recv_pkts, recv_pkts_ok := currentState["ib_recv_pkts"]
xmit_pkts, xmit_pkts_ok := currentState["ib_xmit_pkts"]
if recv_ok && xmit_ok {
if y, err := if y, err :=
lp.New( lp.New(
"ib_total", "ib_total",
info.tagSet, info.tagSet,
m.meta, m.meta,
map[string]interface{}{ map[string]interface{}{
"value": recv + xmit, "value": ib_total,
}, },
now); err == nil { now); err == nil {
y.AddMeta("unit", "bytes") y.AddMeta("unit", "bytes")
output <- y output <- y
} }
}
if recv_pkts_ok && xmit_pkts_ok {
if y, err := if y, err :=
lp.New( lp.New(
"ib_total_pkts", "ib_total_pkts",
info.tagSet, info.tagSet,
m.meta, m.meta,
map[string]interface{}{ map[string]interface{}{
"value": recv_pkts + xmit_pkts, "value": ib_total_pkts,
}, },
now); err == nil { now); err == nil {
y.AddMeta("unit", "packets") y.AddMeta("unit", "packets")
@ -261,7 +304,6 @@ func (m *InfinibandCollector) Read(interval time.Duration, output chan lp.CCMetr
} }
} }
} }
}
} }
func (m *InfinibandCollector) Close() { func (m *InfinibandCollector) Close() {