Skip to content

Commit

Permalink
Add support /sys/devices/system/node/nodeN/meminfo
Browse files Browse the repository at this point in the history
  • Loading branch information
khunafin committed Jan 20, 2023
1 parent affffdb commit 5c470ff
Show file tree
Hide file tree
Showing 5 changed files with 333 additions and 6 deletions.
190 changes: 190 additions & 0 deletions sysfs/meminfo_numa.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
// Copyright 2019 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build linux
// +build linux

package sysfs

import (
"bufio"
"bytes"
"fmt"
"io"
"path/filepath"
"strconv"
"strings"

"github.com/prometheus/procfs/internal/util"
)

// Meminfo represents memory statistics for NUMA node
type Meminfo struct {
MemTotal uint64
MemFree uint64
MemUsed uint64
SwapCached uint64
Active uint64
Inactive uint64
ActiveAnon uint64
InactiveAnon uint64
ActiveFile uint64
InactiveFile uint64
Unevictable uint64
Mlocked uint64
Dirty uint64
Writeback uint64
FilePages uint64
Mapped uint64
AnonPages uint64
Shmem uint64
KernelStack uint64
PageTables uint64
NFS_Unstable uint64
Bounce uint64
WritebackTmp uint64
KReclaimable uint64
Slab uint64
SReclaimable uint64
SUnreclaim uint64
AnonHugePages uint64
ShmemHugePages uint64
ShmemPmdMapped uint64
FileHugePages uint64
FilePmdMapped uint64
HugePages_Total uint64
HugePages_Free uint64
HugePages_Surp uint64
}

func (fs FS) MeminfoNUMA() (map[int]Meminfo, error) {
m := make(map[int]Meminfo)
nodes, err := filepath.Glob(fs.sys.Path(nodePattern))
if err != nil {
return nil, err
}

for _, node := range nodes {
nodeNumbers := nodeNumberRegexp.FindStringSubmatch(node)
if len(nodeNumbers) != 2 {
continue
}
nodeNumber, err := strconv.Atoi(nodeNumbers[1])
if err != nil {
return nil, err
}
b, err := util.ReadFileNoStat(filepath.Join(node, "meminfo"))
if err != nil {
return nil, err
}
meminfo, err := parseMeminfo(bytes.NewReader(b))
if err != nil {
return nil, err
}
m[nodeNumber] = meminfo
}
return m, nil
}

func parseMeminfo(r io.Reader) (Meminfo, error) {
var m Meminfo
s := bufio.NewScanner(r)
for s.Scan() {
// Each line has at least a name and value; we ignore the unit.
// A line example: "Node 0 MemTotal: 395936028 kB"
fields := strings.Fields(s.Text())
if len(fields) < 4 {
return Meminfo{}, fmt.Errorf("malformed meminfo line: %q", s.Text())
}

v, err := strconv.ParseUint(fields[3], 0, 64)
if err != nil {
return Meminfo{}, err
}

switch fields[2] {
case "MemTotal:":
m.MemTotal = v
case "MemFree:":
m.MemFree = v
case "MemUsed:":
m.MemUsed = v
case "SwapCached:":
m.SwapCached = v
case "Active:":
m.Active = v
case "Inactive:":
m.Inactive = v
case "Active(anon):":
m.ActiveAnon = v
case "Inactive(anon):":
m.InactiveAnon = v
case "Active(file):":
m.ActiveFile = v
case "Inactive(file):":
m.InactiveFile = v
case "Unevictable:":
m.Unevictable = v
case "Mlocked:":
m.Mlocked = v
case "Dirty:":
m.Dirty = v
case "Writeback:":
m.Writeback = v
case "FilePages:":
m.FilePages = v
case "Mapped:":
m.Mapped = v
case "AnonPages:":
m.AnonPages = v
case "Shmem:":
m.Shmem = v
case "KernelStack:":
m.KernelStack = v
case "PageTables:":
m.PageTables = v
case "NFS_Unstable:":
m.NFS_Unstable = v
case "Bounce:":
m.Bounce = v
case "WritebackTmp:":
m.WritebackTmp = v
case "KReclaimable:":
m.KReclaimable = v
case "Slab:":
m.Slab = v
case "SReclaimable:":
m.SReclaimable = v
case "SUnreclaim:":
m.SUnreclaim = v
case "AnonHugePages:":
m.AnonHugePages = v
case "ShmemHugePages:":
m.ShmemHugePages = v
case "ShmemPmdMapped:":
m.ShmemPmdMapped = v
case "FileHugePages:":
m.FileHugePages = v
case "FilePmdMapped:":
m.FilePmdMapped = v
case "HugePages_Total:":
m.HugePages_Total = v
case "HugePages_Free:":
m.HugePages_Free = v
case "HugePages_Surp:":
m.HugePages_Surp = v
}
}

return m, nil
}
41 changes: 41 additions & 0 deletions sysfs/meminfo_numa_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2017 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build linux
// +build linux

package sysfs

import (
"testing"
)

func TestMeminfoNUMA(t *testing.T) {
fs, err := NewFS(sysTestFixtures)
if err != nil {
t.Fatal(err)
}

meminfo, err := fs.MeminfoNUMA()
if err != nil {
t.Fatal(err)
}

if want, got := uint64(133), meminfo[1].HugePages_Total; want != got {
t.Errorf("want meminfo stat HugePages_Total value %d, got %d", want, got)
}

if want, got := uint64(134), meminfo[1].HugePages_Free; want != got {
t.Errorf("want meminfo stat HugePages_Free value %d, got %d", want, got)
}
}
24 changes: 24 additions & 0 deletions sysfs/numa.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2017 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build linux
// +build linux

package sysfs

import "regexp"

var (
nodePattern = "devices/system/node/node[0-9]*"
nodeNumberRegexp = regexp.MustCompile(`.*devices/system/node/node([0-9]*)`)
)
6 changes: 0 additions & 6 deletions sysfs/vmstat_numa.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,12 @@ import (
"bytes"
"fmt"
"path/filepath"
"regexp"
"strconv"
"strings"

"github.com/prometheus/procfs/internal/util"
)

var (
nodePattern = "devices/system/node/node[0-9]*"
nodeNumberRegexp = regexp.MustCompile(`.*devices/system/node/node([0-9]*)`)
)

type VMStat struct {
NrFreePages uint64
NrZoneInactiveAnon uint64
Expand Down
78 changes: 78 additions & 0 deletions testdata/fixtures.ttar
Original file line number Diff line number Diff line change
Expand Up @@ -12727,6 +12727,45 @@ Mode: 775
Directory: fixtures/sys/devices/system/node/node1
Mode: 755
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/devices/system/node/node1/meminfo
Lines: 35
Node 1 MemTotal: 101 kB
Node 1 MemFree: 102 kB
Node 1 MemUsed: 103 kB
Node 1 SwapCached: 104 kB
Node 1 Active: 105 kB
Node 1 Inactive: 106 kB
Node 1 Active(anon): 107 kB
Node 1 Inactive(anon): 108 kB
Node 1 Active(file): 109 kB
Node 1 Inactive(file): 110 kB
Node 1 Unevictable: 111 kB
Node 1 Mlocked: 112 kB
Node 1 Dirty: 113 kB
Node 1 Writeback: 114 kB
Node 1 FilePages: 115 kB
Node 1 Mapped: 116 kB
Node 1 AnonPages: 117 kB
Node 1 Shmem: 118 kB
Node 1 KernelStack: 119 kB
Node 1 PageTables: 120 kB
Node 1 NFS_Unstable: 121 kB
Node 1 Bounce: 122 kB
Node 1 WritebackTmp: 123 kB
Node 1 KReclaimable: 124 kB
Node 1 Slab: 125 kB
Node 1 SReclaimable: 126 kB
Node 1 SUnreclaim: 127 kB
Node 1 AnonHugePages: 128 kB
Node 1 ShmemHugePages: 129 kB
Node 1 ShmemPmdMapped: 130 kB
Node 1 FileHugePages: 131 kB
Node 1 FilePmdMapped: 132 kB
Node 1 HugePages_Total: 133
Node 1 HugePages_Free: 134
Node 1 HugePages_Surp: 135EOF
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/devices/system/node/node1/vmstat
Lines: 6
nr_free_pages 1
Expand All @@ -12740,6 +12779,45 @@ Mode: 644
Directory: fixtures/sys/devices/system/node/node2
Mode: 755
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/devices/system/node/node2/meminfo
Lines: 35
Node 2 MemTotal: 201 kB
Node 2 MemFree: 202 kB
Node 2 MemUsed: 203 kB
Node 2 SwapCached: 204 kB
Node 2 Active: 205 kB
Node 2 Inactive: 206 kB
Node 2 Active(anon): 207 kB
Node 2 Inactive(anon): 208 kB
Node 2 Active(file): 209 kB
Node 2 Inactive(file): 210 kB
Node 2 Unevictable: 211 kB
Node 2 Mlocked: 212 kB
Node 2 Dirty: 213 kB
Node 2 Writeback: 214 kB
Node 2 FilePages: 215 kB
Node 2 Mapped: 216 kB
Node 2 AnonPages: 217 kB
Node 2 Shmem: 218 kB
Node 2 KernelStack: 219 kB
Node 2 PageTables: 220 kB
Node 2 NFS_Unstable: 221 kB
Node 2 Bounce: 222 kB
Node 2 WritebackTmp: 223 kB
Node 2 KReclaimable: 224 kB
Node 2 Slab: 225 kB
Node 2 SReclaimable: 226 kB
Node 2 SUnreclaim: 227 kB
Node 2 AnonHugePages: 228 kB
Node 2 ShmemHugePages: 229 kB
Node 2 ShmemPmdMapped: 230 kB
Node 2 FileHugePages: 231 kB
Node 2 FilePmdMapped: 232 kB
Node 2 HugePages_Total: 233
Node 2 HugePages_Free: 234
Node 2 HugePages_Surp: 235EOF
Mode: 644
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Path: fixtures/sys/devices/system/node/node2/vmstat
Lines: 6
nr_free_pages 7
Expand Down

0 comments on commit 5c470ff

Please sign in to comment.