Skip to content

Commit 1351ae1

Browse files
authored
Merge pull request #348 from jay-mckay/main
Read cpu.stat regardless if controller enabled.
2 parents 8de881b + 707e4b4 commit 1351ae1

File tree

1 file changed

+109
-89
lines changed

1 file changed

+109
-89
lines changed

cgroup2/manager.go

Lines changed: 109 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -559,114 +559,134 @@ func (c *Manager) MoveTo(destination *Manager) error {
559559
}
560560

561561
func (c *Manager) Stat() (*stats.Metrics, error) {
562-
controllers, err := c.Controllers()
563-
if err != nil {
564-
return nil, err
565-
}
566-
// Sizing this avoids an allocation to increase the map at runtime;
567-
// currently the default bucket size is 8 and we put 40+ elements
568-
// in it so we'd always end up allocating.
569-
out := make(map[string]uint64, 50)
570-
for _, controller := range controllers {
571-
switch controller {
572-
case "cpu", "memory":
573-
if err := readKVStatsFile(c.path, controller+".stat", out); err != nil {
574-
if os.IsNotExist(err) {
575-
continue
576-
}
577-
return nil, err
578-
}
579-
}
580-
}
581-
memoryEvents := make(map[string]uint64)
582-
if err := readKVStatsFile(c.path, "memory.events", memoryEvents); err != nil {
583-
if !os.IsNotExist(err) {
584-
return nil, err
585-
}
586-
}
587-
588562
var metrics stats.Metrics
563+
var err error
564+
589565
metrics.Pids = &stats.PidsStat{
590566
Current: getStatFileContentUint64(filepath.Join(c.path, "pids.current")),
591567
Limit: getStatFileContentUint64(filepath.Join(c.path, "pids.max")),
592568
}
593-
metrics.CPU = &stats.CPUStat{
594-
UsageUsec: out["usage_usec"],
595-
UserUsec: out["user_usec"],
596-
SystemUsec: out["system_usec"],
597-
NrPeriods: out["nr_periods"],
598-
NrThrottled: out["nr_throttled"],
599-
ThrottledUsec: out["throttled_usec"],
600-
PSI: getStatPSIFromFile(filepath.Join(c.path, "cpu.pressure")),
601-
}
602-
if nr_bursts, ok := out["nr_bursts"]; ok {
603-
metrics.CPU.NrBursts = nr_bursts
604-
}
605-
if burst_usec, ok := out["burst_usec"]; ok {
606-
metrics.CPU.BurstUsec = burst_usec
607-
}
608-
metrics.Memory = &stats.MemoryStat{
609-
Anon: out["anon"],
610-
File: out["file"],
611-
KernelStack: out["kernel_stack"],
612-
Slab: out["slab"],
613-
Sock: out["sock"],
614-
Shmem: out["shmem"],
615-
FileMapped: out["file_mapped"],
616-
FileDirty: out["file_dirty"],
617-
FileWriteback: out["file_writeback"],
618-
AnonThp: out["anon_thp"],
619-
InactiveAnon: out["inactive_anon"],
620-
ActiveAnon: out["active_anon"],
621-
InactiveFile: out["inactive_file"],
622-
ActiveFile: out["active_file"],
623-
Unevictable: out["unevictable"],
624-
SlabReclaimable: out["slab_reclaimable"],
625-
SlabUnreclaimable: out["slab_unreclaimable"],
626-
Pgfault: out["pgfault"],
627-
Pgmajfault: out["pgmajfault"],
628-
WorkingsetRefault: out["workingset_refault"],
629-
WorkingsetActivate: out["workingset_activate"],
630-
WorkingsetNodereclaim: out["workingset_nodereclaim"],
631-
Pgrefill: out["pgrefill"],
632-
Pgscan: out["pgscan"],
633-
Pgsteal: out["pgsteal"],
634-
Pgactivate: out["pgactivate"],
635-
Pgdeactivate: out["pgdeactivate"],
636-
Pglazyfree: out["pglazyfree"],
637-
Pglazyfreed: out["pglazyfreed"],
638-
ThpFaultAlloc: out["thp_fault_alloc"],
639-
ThpCollapseAlloc: out["thp_collapse_alloc"],
640-
Usage: getStatFileContentUint64(filepath.Join(c.path, "memory.current")),
641-
UsageLimit: getStatFileContentUint64(filepath.Join(c.path, "memory.max")),
642-
MaxUsage: getStatFileContentUint64(filepath.Join(c.path, "memory.peak")),
643-
SwapUsage: getStatFileContentUint64(filepath.Join(c.path, "memory.swap.current")),
644-
SwapLimit: getStatFileContentUint64(filepath.Join(c.path, "memory.swap.max")),
645-
SwapMaxUsage: getStatFileContentUint64(filepath.Join(c.path, "memory.swap.peak")),
646-
PSI: getStatPSIFromFile(filepath.Join(c.path, "memory.pressure")),
647-
}
648-
if len(memoryEvents) > 0 {
649-
metrics.MemoryEvents = &stats.MemoryEvents{
650-
Low: memoryEvents["low"],
651-
High: memoryEvents["high"],
652-
Max: memoryEvents["max"],
653-
Oom: memoryEvents["oom"],
654-
OomKill: memoryEvents["oom_kill"],
655-
}
569+
570+
metrics.CPU, err = readCPUStats(c.path)
571+
if err != nil {
572+
return nil, err
573+
}
574+
575+
metrics.Memory, err = readMemoryStats(c.path)
576+
if err != nil {
577+
return nil, err
578+
}
579+
580+
metrics.MemoryEvents, err = readMemoryEvents(c.path)
581+
if err != nil {
582+
return nil, err
656583
}
584+
657585
metrics.Io = &stats.IOStat{
658586
Usage: readIoStats(c.path),
659587
PSI: getStatPSIFromFile(filepath.Join(c.path, "io.pressure")),
660588
}
589+
661590
metrics.Rdma = &stats.RdmaStat{
662591
Current: rdmaStats(filepath.Join(c.path, "rdma.current")),
663592
Limit: rdmaStats(filepath.Join(c.path, "rdma.max")),
664593
}
594+
665595
metrics.Hugetlb = readHugeTlbStats(c.path)
666596

667597
return &metrics, nil
668598
}
669599

600+
func readCPUStats(cgroupPath string) (*stats.CPUStat, error) {
601+
cpuStat := make(map[string]uint64)
602+
if err := readKVStatsFile(cgroupPath, "cpu.stat", cpuStat); err != nil {
603+
if os.IsNotExist(err) {
604+
return &stats.CPUStat{}, nil
605+
}
606+
return nil, err
607+
}
608+
return &stats.CPUStat{
609+
UsageUsec: cpuStat["usage_usec"],
610+
UserUsec: cpuStat["user_usec"],
611+
SystemUsec: cpuStat["system_usec"],
612+
NrPeriods: cpuStat["nr_periods"],
613+
NrThrottled: cpuStat["nr_throttled"],
614+
ThrottledUsec: cpuStat["throttled_usec"],
615+
NrBursts: cpuStat["nr_bursts"],
616+
BurstUsec: cpuStat["burst_usec"],
617+
PSI: getStatPSIFromFile(filepath.Join(cgroupPath, "cpu.pressure")),
618+
}, nil
619+
}
620+
621+
func readMemoryStats(cgroupPath string) (*stats.MemoryStat, error) {
622+
memoryStat := make(map[string]uint64, 40)
623+
if err := readKVStatsFile(cgroupPath, "memory.stat", memoryStat); err != nil {
624+
if os.IsNotExist(err) {
625+
return &stats.MemoryStat{}, nil
626+
}
627+
return nil, err
628+
}
629+
return &stats.MemoryStat{
630+
Anon: memoryStat["anon"],
631+
File: memoryStat["file"],
632+
KernelStack: memoryStat["kernel_stack"],
633+
Slab: memoryStat["slab"],
634+
Sock: memoryStat["sock"],
635+
Shmem: memoryStat["shmem"],
636+
FileMapped: memoryStat["file_mapped"],
637+
FileDirty: memoryStat["file_dirty"],
638+
FileWriteback: memoryStat["file_writeback"],
639+
AnonThp: memoryStat["anon_thp"],
640+
InactiveAnon: memoryStat["inactive_anon"],
641+
ActiveAnon: memoryStat["active_anon"],
642+
InactiveFile: memoryStat["inactive_file"],
643+
ActiveFile: memoryStat["active_file"],
644+
Unevictable: memoryStat["unevictable"],
645+
SlabReclaimable: memoryStat["slab_reclaimable"],
646+
SlabUnreclaimable: memoryStat["slab_unreclaimable"],
647+
Pgfault: memoryStat["pgfault"],
648+
Pgmajfault: memoryStat["pgmajfault"],
649+
WorkingsetRefault: memoryStat["workingset_refault"],
650+
WorkingsetActivate: memoryStat["workingset_activate"],
651+
WorkingsetNodereclaim: memoryStat["workingset_nodereclaim"],
652+
Pgrefill: memoryStat["pgrefill"],
653+
Pgscan: memoryStat["pgscan"],
654+
Pgsteal: memoryStat["pgsteal"],
655+
Pgactivate: memoryStat["pgactivate"],
656+
Pgdeactivate: memoryStat["pgdeactivate"],
657+
Pglazyfree: memoryStat["pglazyfree"],
658+
Pglazyfreed: memoryStat["pglazyfreed"],
659+
ThpFaultAlloc: memoryStat["thp_fault_alloc"],
660+
ThpCollapseAlloc: memoryStat["thp_collapse_alloc"],
661+
Usage: getStatFileContentUint64(filepath.Join(cgroupPath, "memory.current")),
662+
UsageLimit: getStatFileContentUint64(filepath.Join(cgroupPath, "memory.max")),
663+
MaxUsage: getStatFileContentUint64(filepath.Join(cgroupPath, "memory.peak")),
664+
SwapUsage: getStatFileContentUint64(filepath.Join(cgroupPath, "memory.swap.current")),
665+
SwapLimit: getStatFileContentUint64(filepath.Join(cgroupPath, "memory.swap.max")),
666+
SwapMaxUsage: getStatFileContentUint64(filepath.Join(cgroupPath, "memory.swap.peak")),
667+
PSI: getStatPSIFromFile(filepath.Join(cgroupPath, "memory.pressure")),
668+
}, nil
669+
}
670+
671+
func readMemoryEvents(cgroupPath string) (*stats.MemoryEvents, error) {
672+
memoryEvents := make(map[string]uint64)
673+
if err := readKVStatsFile(cgroupPath, "memory.events", memoryEvents); err != nil {
674+
if !os.IsNotExist(err) {
675+
return nil, err
676+
}
677+
}
678+
if len(memoryEvents) == 0 {
679+
return nil, nil
680+
}
681+
return &stats.MemoryEvents{
682+
Low: memoryEvents["low"],
683+
High: memoryEvents["high"],
684+
Max: memoryEvents["max"],
685+
Oom: memoryEvents["oom"],
686+
OomKill: memoryEvents["oom_kill"],
687+
}, nil
688+
}
689+
670690
func readKVStatsFile(path string, file string, out map[string]uint64) error {
671691
f, err := os.Open(filepath.Join(path, file))
672692
if err != nil {

0 commit comments

Comments
 (0)