Skip to content

Commit

Permalink
python: tools: Add tool for displaying a list of realtime data
Browse files Browse the repository at this point in the history
Add a tool for displaying the realtime allocations for a cgroup
hierarchy.

$ ./src/tools/cgrealtimelist.py -C application.sliceRUNTIME  PERIOD PERCENT CGROUP
   1000    8000  12.50% /child2.service
   5000  100000   5.00% /child1.service
  20000 1000000   2.00% /child3.service

10,000 / 50,000 microseconds (20.00%) of the CPU cycles have been allocated to realtime in the root cgroup.

9,750 of the 10,000 realtime cycles (97.50%) for /application.slice have been assigned to children cgroups

5,000 (cpu.rt_runtime_us) / 1,000,000 (cpu.rt_period_us) microseconds can still be assigned to a child of /application.slice

Note that the remaining cpu.rt_runtime_us is estimated and could be off by 1 or 2 in either direction.

$ ./src/tools/cgrealtimelist.py
RUNTIME  PERIOD PERCENT CGROUP
  10000   50000  20.00% /application.slice
   1000    8000  12.50% /application.slice/child2.service
  10000   90000  11.11% /system.slice
   5000  100000   5.00% /application.slice/child1.service
   1000   25000   4.00% /user.slice
   1000   50000   2.00% /system.slice/firewalld.service
  20000 1000000   2.00% /application.slice/child3.service
   1000   70000   1.43% /system.slice/systemd-udevd.service
   1000  100000   1.00% /init.scope

950,000 / 1,000,000 microseconds (95.00%) of the CPU cycles have been allocated to realtime in the root cgroup.

361,111 of the 950,000 realtime cycles (38.01%) for the root cgroup have been assigned to children cgroups

588,888 (cpu.rt_runtime_us) / 1,000,000 (cpu.rt_period_us) microseconds can still be assigned to a child of the root cgroup

Note that the remaining cpu.rt_runtime_us is estimated and could be off by 1 or 2 in either direction.

Signed-off-by: Tom Hromatka <[email protected]>
  • Loading branch information
drakenclimber committed Apr 25, 2024
1 parent 13d3ecc commit 367f08a
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 0 deletions.
75 changes: 75 additions & 0 deletions src/python/libcgroup.pyx.m4
Original file line number Diff line number Diff line change
Expand Up @@ -1260,6 +1260,81 @@ class LibcgroupPsiList(LibcgroupTree):
else:
self._show_float()

class LibcgroupRealtimeList(LibcgroupTree):
def __init__(self, name, depth=None, limit=None):
super().__init__(name, version=Version.CGROUP_V1, controller='cpu',
depth=depth)

self.rootcg.get_realtime()
self.cglist = list()
self.limit = limit

def walk_action(self, cg):
cg.get_realtime()

if cg.settings['cpu.rt_runtime_us']:
self.cglist.append(cg)

def sort(self):
self.cglist = sorted(self.cglist, reverse=True,
key=lambda cg: cg.realtime_pct)

def show(self, sort=True, verbose=True):
total_pct = 0.0

if sort:
self.sort()

print('{0: >7} {1: >7} {2: >7} {3: <20}'.`format'('RUNTIME', 'PERIOD', 'PERCENT', 'CGROUP'))

for i, cg in enumerate(self.cglist):
# Only add the realtime of the direct children of the root cgroup.
# Grandchildren realtime allocations are accounted for in their
# parents' realtime allocations.
if cg.path[`len'(self.rootcg.path):].count('/') == 1:
total_pct += cg.realtime_pct

if self.limit and i >= self.limit:
continue

print('{0: >7} {1: >7} {2: >5.2f}% {3: <20}'.`format'(
cg.settings['cpu.rt_runtime_us'],
cg.settings['cpu.rt_period_us'],
cg.realtime_pct,
cg.path[`len'(self.start_path):]))

if verbose:
print('\n{0:,} / {1:,} microseconds ({2: >5.2f}%) of the CPU '
'cycles have been allocated to realtime in the root '
'cgroup.'.`format'(
self.rootcg.settings['cpu.rt_runtime_us'],
self.rootcg.settings['cpu.rt_period_us'],
self.rootcg.realtime_pct))

if self.mount == self.start_path:
alloc_path = 'the root cgroup'
tmpcg = self.rootcg
else:
alloc_path = self.rootcg.path[`len'(self.mount):]
tmpcg = self.rootcg

percent_consumed = 100 * total_pct / tmpcg.realtime_pct
print('\n{0:,} of the {1:,} realtime cycles ({2: >5.2f}%) for {3:} '
'have been assigned to children cgroups'.`format'(
int(percent_consumed * tmpcg.settings['cpu.rt_runtime_us'] / 100),
tmpcg.settings['cpu.rt_runtime_us'],
percent_consumed,
alloc_path))

print('\n{0:,} (cpu.rt_runtime_us) / {1:,} (cpu.rt_period_us) '
'microseconds can still be assigned to a child of {2:}'.`format'(
max(int((tmpcg.realtime_pct - total_pct) * 10000), 0),
1000000,
alloc_path))

print('\nNote that the remaining cpu.rt_runtime_us is estimated '
'and could be off by 1 or 2 in either direction.\n')

class LibcgroupPid(object):
def __init__(self, pid, command=None):
self.pid = pid
Expand Down
1 change: 1 addition & 0 deletions src/tools/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ if ENABLE_PYTHON
EXTRA_DIST = \
cgpsilist.py \
cgpsitree.py \
cgrealtimelist.py \
cgrealtimetree.py
endif

Expand Down
35 changes: 35 additions & 0 deletions src/tools/cgrealtimelist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-only
#
# Display a list of cgroups and their realtime usage
#
# Copyright (c) 2021-2024 Oracle and/or its affiliates.
# Author: Tom Hromatka <[email protected]>
#

from libcgroup import LibcgroupRealtimeList
import argparse
import os

def parse_args():
parser = argparse.ArgumentParser('Libcgroup PSI List')
parser.add_argument('-C', '--cgroup', type=str, required=False, default=None,
help='Relative path to the cgroup of interest, e.g. machine.slice/foo.scope')
parser.add_argument('-d', '--depth', type=int, required=False, default=None,
help='Depth to recurse into the cgroup path. 0 == only this cgroup, 1 == this cgroup and its children, ...')
parser.add_argument('-l', '--limit', type=int, required=False, default=None,
help='Only display the first N cgroups. If not provided, all cgroups that match are displayed')

args = parser.parse_args()

return args

def main(args):
cglist = LibcgroupRealtimeList(args.cgroup, depth=args.depth, limit=args.limit)

cglist.walk()
cglist.show()

if __name__ == '__main__':
args = parse_args()
main(args)

0 comments on commit 367f08a

Please sign in to comment.