162306a36Sopenharmony_ci#!/usr/bin/env python3
262306a36Sopenharmony_ci#
362306a36Sopenharmony_ci# Copyright (C) 2022 Roman Gushchin <roman.gushchin@linux.dev>
462306a36Sopenharmony_ci# Copyright (C) 2022 Meta
562306a36Sopenharmony_ci
662306a36Sopenharmony_ciimport os
762306a36Sopenharmony_ciimport argparse
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci
1062306a36Sopenharmony_cidef scan_cgroups(cgroup_root):
1162306a36Sopenharmony_ci    cgroups = {}
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci    for root, subdirs, _ in os.walk(cgroup_root):
1462306a36Sopenharmony_ci        for cgroup in subdirs:
1562306a36Sopenharmony_ci            path = os.path.join(root, cgroup)
1662306a36Sopenharmony_ci            ino = os.stat(path).st_ino
1762306a36Sopenharmony_ci            cgroups[ino] = path
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci    # (memcg ino, path)
2062306a36Sopenharmony_ci    return cgroups
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cidef scan_shrinkers(shrinker_debugfs):
2462306a36Sopenharmony_ci    shrinkers = []
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci    for root, subdirs, _ in os.walk(shrinker_debugfs):
2762306a36Sopenharmony_ci        for shrinker in subdirs:
2862306a36Sopenharmony_ci            count_path = os.path.join(root, shrinker, "count")
2962306a36Sopenharmony_ci            with open(count_path) as f:
3062306a36Sopenharmony_ci                for line in f.readlines():
3162306a36Sopenharmony_ci                    items = line.split(' ')
3262306a36Sopenharmony_ci                    ino = int(items[0])
3362306a36Sopenharmony_ci                    # (count, shrinker, memcg ino)
3462306a36Sopenharmony_ci                    shrinkers.append((int(items[1]), shrinker, ino))
3562306a36Sopenharmony_ci    return shrinkers
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cidef main():
3962306a36Sopenharmony_ci    parser = argparse.ArgumentParser(description='Display biggest shrinkers')
4062306a36Sopenharmony_ci    parser.add_argument('-n', '--lines', type=int, help='Number of lines to print')
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci    args = parser.parse_args()
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci    cgroups = scan_cgroups("/sys/fs/cgroup/")
4562306a36Sopenharmony_ci    shrinkers = scan_shrinkers("/sys/kernel/debug/shrinker/")
4662306a36Sopenharmony_ci    shrinkers.sort(reverse = True, key = lambda x: x[0])
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci    n = 0
4962306a36Sopenharmony_ci    for s in shrinkers:
5062306a36Sopenharmony_ci        count, name, ino = (s[0], s[1], s[2])
5162306a36Sopenharmony_ci        if count == 0:
5262306a36Sopenharmony_ci            break
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci        if ino == 0 or ino == 1:
5562306a36Sopenharmony_ci            cg = "/"
5662306a36Sopenharmony_ci        else:
5762306a36Sopenharmony_ci            try:
5862306a36Sopenharmony_ci                cg = cgroups[ino]
5962306a36Sopenharmony_ci            except KeyError:
6062306a36Sopenharmony_ci                cg = "unknown (%d)" % ino
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci        print("%-8s %-20s %s" % (count, name, cg))
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci        n += 1
6562306a36Sopenharmony_ci        if args.lines and n >= args.lines:
6662306a36Sopenharmony_ci            break
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ciif __name__ == '__main__':
7062306a36Sopenharmony_ci    main()
71