Skip to content

Commit f27d233

Browse files
committed
Read cpu.stat regardless if controller enabled.
The unified hierarchy provides the cpu.stat file for every cgroup, regardless if the CPU controller is enabled (in fact, setting the systemd property CPUAccounting=True does not enable this controller because of this fact). It provides the usage_usec, user_usec, and system_usec by default. Instead of reading the stat for each enabled controller (CPU and memory), just attempt to read them each time the Stat() function is called. Attempting to read the memory.stat file even if memory accounting is not enabled seems insignificant (some other files always have a read attempt, such as memory.current), and eliminates finding and looping over enabled controllers. Resolves: #347 Signed-off-by: Jackson McKay <jackjaymckay@gmail.com>
1 parent bce3c7e commit f27d233

File tree

1 file changed

+54
-64
lines changed

1 file changed

+54
-64
lines changed

cgroup2/manager.go

+54-64
Original file line numberDiff line numberDiff line change
@@ -550,78 +550,61 @@ func (c *Manager) MoveTo(destination *Manager) error {
550550
}
551551

552552
func (c *Manager) Stat() (*stats.Metrics, error) {
553-
controllers, err := c.Controllers()
554-
if err != nil {
555-
return nil, err
556-
}
557-
// Sizing this avoids an allocation to increase the map at runtime;
558-
// currently the default bucket size is 8 and we put 40+ elements
559-
// in it so we'd always end up allocating.
560-
out := make(map[string]uint64, 50)
561-
for _, controller := range controllers {
562-
switch controller {
563-
case "cpu", "memory":
564-
if err := readKVStatsFile(c.path, controller+".stat", out); err != nil {
565-
if os.IsNotExist(err) {
566-
continue
567-
}
568-
return nil, err
569-
}
570-
}
571-
}
572-
memoryEvents := make(map[string]uint64)
573-
if err := readKVStatsFile(c.path, "memory.events", memoryEvents); err != nil {
553+
var metrics stats.Metrics
554+
555+
cpuStat := make(map[string]uint64)
556+
if err := readKVStatsFile(c.path, "cpu.stat", cpuStat); err != nil {
574557
if !os.IsNotExist(err) {
575558
return nil, err
576559
}
577560
}
578-
579-
var metrics stats.Metrics
580-
metrics.Pids = &stats.PidsStat{
581-
Current: getStatFileContentUint64(filepath.Join(c.path, "pids.current")),
582-
Limit: getStatFileContentUint64(filepath.Join(c.path, "pids.max")),
583-
}
584561
metrics.CPU = &stats.CPUStat{
585-
UsageUsec: out["usage_usec"],
586-
UserUsec: out["user_usec"],
587-
SystemUsec: out["system_usec"],
588-
NrPeriods: out["nr_periods"],
589-
NrThrottled: out["nr_throttled"],
590-
ThrottledUsec: out["throttled_usec"],
562+
UsageUsec: cpuStat["usage_usec"],
563+
UserUsec: cpuStat["user_usec"],
564+
SystemUsec: cpuStat["system_usec"],
565+
NrPeriods: cpuStat["nr_periods"],
566+
NrThrottled: cpuStat["nr_throttled"],
567+
ThrottledUsec: cpuStat["throttled_usec"],
591568
PSI: getStatPSIFromFile(filepath.Join(c.path, "cpu.pressure")),
592569
}
570+
memoryStat := make(map[string]uint64, 40)
571+
if err := readKVStatsFile(c.path, "memory.stat", memoryStat); err != nil {
572+
if !os.IsNotExist(err) {
573+
return nil, err
574+
}
575+
}
593576
metrics.Memory = &stats.MemoryStat{
594-
Anon: out["anon"],
595-
File: out["file"],
596-
KernelStack: out["kernel_stack"],
597-
Slab: out["slab"],
598-
Sock: out["sock"],
599-
Shmem: out["shmem"],
600-
FileMapped: out["file_mapped"],
601-
FileDirty: out["file_dirty"],
602-
FileWriteback: out["file_writeback"],
603-
AnonThp: out["anon_thp"],
604-
InactiveAnon: out["inactive_anon"],
605-
ActiveAnon: out["active_anon"],
606-
InactiveFile: out["inactive_file"],
607-
ActiveFile: out["active_file"],
608-
Unevictable: out["unevictable"],
609-
SlabReclaimable: out["slab_reclaimable"],
610-
SlabUnreclaimable: out["slab_unreclaimable"],
611-
Pgfault: out["pgfault"],
612-
Pgmajfault: out["pgmajfault"],
613-
WorkingsetRefault: out["workingset_refault"],
614-
WorkingsetActivate: out["workingset_activate"],
615-
WorkingsetNodereclaim: out["workingset_nodereclaim"],
616-
Pgrefill: out["pgrefill"],
617-
Pgscan: out["pgscan"],
618-
Pgsteal: out["pgsteal"],
619-
Pgactivate: out["pgactivate"],
620-
Pgdeactivate: out["pgdeactivate"],
621-
Pglazyfree: out["pglazyfree"],
622-
Pglazyfreed: out["pglazyfreed"],
623-
ThpFaultAlloc: out["thp_fault_alloc"],
624-
ThpCollapseAlloc: out["thp_collapse_alloc"],
577+
Anon: memoryStat["anon"],
578+
File: memoryStat["file"],
579+
KernelStack: memoryStat["kernel_stack"],
580+
Slab: memoryStat["slab"],
581+
Sock: memoryStat["sock"],
582+
Shmem: memoryStat["shmem"],
583+
FileMapped: memoryStat["file_mapped"],
584+
FileDirty: memoryStat["file_dirty"],
585+
FileWriteback: memoryStat["file_writeback"],
586+
AnonThp: memoryStat["anon_thp"],
587+
InactiveAnon: memoryStat["inactive_anon"],
588+
ActiveAnon: memoryStat["active_anon"],
589+
InactiveFile: memoryStat["inactive_file"],
590+
ActiveFile: memoryStat["active_file"],
591+
Unevictable: memoryStat["unevictable"],
592+
SlabReclaimable: memoryStat["slab_reclaimable"],
593+
SlabUnreclaimable: memoryStat["slab_unreclaimable"],
594+
Pgfault: memoryStat["pgfault"],
595+
Pgmajfault: memoryStat["pgmajfault"],
596+
WorkingsetRefault: memoryStat["workingset_refault"],
597+
WorkingsetActivate: memoryStat["workingset_activate"],
598+
WorkingsetNodereclaim: memoryStat["workingset_nodereclaim"],
599+
Pgrefill: memoryStat["pgrefill"],
600+
Pgscan: memoryStat["pgscan"],
601+
Pgsteal: memoryStat["pgsteal"],
602+
Pgactivate: memoryStat["pgactivate"],
603+
Pgdeactivate: memoryStat["pgdeactivate"],
604+
Pglazyfree: memoryStat["pglazyfree"],
605+
Pglazyfreed: memoryStat["pglazyfreed"],
606+
ThpFaultAlloc: memoryStat["thp_fault_alloc"],
607+
ThpCollapseAlloc: memoryStat["thp_collapse_alloc"],
625608
Usage: getStatFileContentUint64(filepath.Join(c.path, "memory.current")),
626609
UsageLimit: getStatFileContentUint64(filepath.Join(c.path, "memory.max")),
627610
MaxUsage: getStatFileContentUint64(filepath.Join(c.path, "memory.peak")),
@@ -630,6 +613,13 @@ func (c *Manager) Stat() (*stats.Metrics, error) {
630613
SwapMaxUsage: getStatFileContentUint64(filepath.Join(c.path, "memory.swap.peak")),
631614
PSI: getStatPSIFromFile(filepath.Join(c.path, "memory.pressure")),
632615
}
616+
617+
memoryEvents := make(map[string]uint64)
618+
if err := readKVStatsFile(c.path, "memory.events", memoryEvents); err != nil {
619+
if !os.IsNotExist(err) {
620+
return nil, err
621+
}
622+
}
633623
if len(memoryEvents) > 0 {
634624
metrics.MemoryEvents = &stats.MemoryEvents{
635625
Low: memoryEvents["low"],

0 commit comments

Comments
 (0)