-
Notifications
You must be signed in to change notification settings - Fork 341
/
cputop.py
executable file
·134 lines (118 loc) · 3.49 KB
/
cputop.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#!/usr/bin/env python3
# query cpu topology and print all matching cpu numbers
# cputop "query" ["format"]
# query is a python expression, using variables:
# socket, core, thread, type, cpu
# or "offline" to query all offline cpus
# or "atom" or "core" to select core types
# type can be "atom" or "core"
# cpu is the cpu number
# format is a printf format with %d
# %d will be replaced with the cpu number
# format can be offline to offline the cpu or online to online
# Author: Andi Kleen
from __future__ import print_function
import sys
import os
import re
import argparse
import glob
def numfile(fn):
f = open(fn, "r")
v = int(f.read())
f.close()
return v
outstr = ""
def output(p, fmt):
if fmt:
if fmt == "taskset":
global outstr
if outstr:
outstr += ","
else:
outstr += "taskset -c "
outstr += "%d" % p
else:
print(fmt % (p,))
else:
print(p)
ap = argparse.ArgumentParser(description='''
query cpu topology and print all matching cpu numbers
cputop "query" ["format"]
query is a python expression, using variables:
socket, core, thread, type, cpu
type is "core" or "atom" on a hybrid system
cpu is the cpu number
or "offline" to query all offline cpus
format is a printf format with %d
%d will be replaced with the cpu number, or online/offline
to generate online/offline commands, or taskset to generate taskset command line''',
epilog='''
Examples:
print all cores on socket 0
cputop "socket == 0"
print all first threads in each core on socket 0
cputop "thread == 0 and socket == 0"
disable all second threads (disable hyper threading)
cputop "thread == 1" offline
reenable all offlined cpus
cputop offline online
print all online cpus
cputop True ''', formatter_class=argparse.RawTextHelpFormatter)
ap.add_argument('expr', help='python expression with socket/core/thread')
ap.add_argument('fmt', help='Output format string with %%d, or online/offline', nargs='?')
args = ap.parse_args()
if args.expr == "atom":
args.expr = 'type == "atom"'
if args.expr == "core":
args.expr = 'type == "core"'
special = {
"offline": "echo 0 > /sys/devices/system/cpu/cpu%d/online",
"online": "echo 1 > /sys/devices/system/cpu/cpu%d/online",
}
if args.fmt in special:
args.fmt = special[args.fmt]
types = dict()
for fn in glob.glob("/sys/devices/cpu_*/cpus"):
typ = os.path.basename(fn.replace("/cpus", "")).replace("cpu_","")
cpus = open(fn).read()
for j in cpus.split(","):
m = re.match(r'(\d+)(-\d+)?', j)
if m is None:
continue
if m.group(2):
for k in range(int(m.group(1)), int(m.group(2)[1:])+1):
types[k] = typ
else:
types[int(m.group(1))] = typ
base = "/sys/devices/system/cpu/"
p = {}
l = os.listdir(base)
for d in l:
m = re.match(r"cpu([0-9]+)", d)
if not m:
continue
proc = int(m.group(1))
top = base + d + "/topology"
if not os.path.exists(top):
if args.expr == "offline":
output(proc, args.fmt)
continue
socket = numfile(top + "/physical_package_id")
core = numfile(top + "/core_id")
n = 0
while (socket, core, n) in p:
n += 1
p[(socket, core, n)] = proc
if args.expr == "offline":
sys.exit(0)
for j in sorted(p.keys()):
socket, core, thread = j
cpu = p[j]
type = "any"
if cpu in types:
type = types[cpu]
if eval(args.expr):
output(p[j], args.fmt)
if outstr:
print(outstr)