Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tools/test/hwpmc/pmctest.py
105175 views
1
#!/usr/bin/env python
2
# SPDX-License-Identifier: BSD-3-Clause
3
#
4
# Copyright (c) 2012, Neville-Neil Consulting
5
# Copyright (c) 2026, George V. Neville-Neil
6
# All rights reserved.
7
#
8
9
# Description: A program to run a simple program against every available
10
# pmc counter present in a system.
11
#
12
# To use:
13
#
14
# pmctest.py -p ls > /dev/null
15
#
16
# This should result in ls being run with every available counter
17
# and the system should neither lock up nor panic.
18
#
19
# The default is not to wait after each counter is tested. Since the
20
# prompt would go to stdout you won't see it, just press return
21
# to continue or Ctrl-D to stop.
22
23
import sys
24
import subprocess
25
from subprocess import PIPE
26
import argparse
27
import tempfile
28
from pathlib import Path
29
import os
30
31
def gather_counters():
32
"""Run program and return output as array of lines."""
33
result = subprocess.run("pmccontrol -L", shell=True, capture_output=True, text=True)
34
tabbed = result.stdout.strip().split('\n')
35
return [line.replace('\t', '') for line in tabbed]
36
37
# A list of strings that are not really counters, just
38
# name tags that are output by pmccontrol -L
39
notcounter = ["IAF", "IAP", "TSC", "UNC", "UCF", "UCP", "SOFT" ]
40
41
def main():
42
43
parser = argparse.ArgumentParser(description='Exercise a program under hwpmc')
44
parser.add_argument('--program', type=str, required=True, help='target program')
45
parser.add_argument('--wait', action='store_true', help='Wait after each counter.')
46
parser.add_argument('--count', action='store_true', help='Exercise the program being studied using counting mode pmcs.')
47
parser.add_argument('--sample', action='store_true', help='Exercise the program being studied using sampling mode pmcs.')
48
49
args = parser.parse_args()
50
51
counters = gather_counters()
52
53
if len(counters) <= 0:
54
print("no counters found")
55
sys.exit()
56
57
if args.count == True and args.sample == True:
58
print("Choose one of --count OR --sample.")
59
sys.exit()
60
61
program = Path(args.program).name
62
63
if args.count == True:
64
tmpdir = tempfile.mkdtemp(prefix=program + "-", suffix="-counting-pmc")
65
print("Exercising program ", args.program, " storing results data in ", tmpdir)
66
67
if args.sample == True:
68
tmpdir = tempfile.mkdtemp(prefix=program + "-", suffix="-sampling-pmc")
69
print("Exercising program ", args.program, " storing results data in ", tmpdir)
70
71
for counter in counters:
72
if counter in notcounter:
73
continue
74
if args.count == True:
75
with open(tmpdir + "/" + program + "-" + counter + ".txt", 'w') as file:
76
p = subprocess.Popen(["pmcstat",
77
"-p", counter, args.program],
78
text=True, stderr=file, stdout=file)
79
result = p.wait()
80
print(result)
81
elif args.sample == True:
82
pmcout = tmpdir + "/" + program + "-" + counter + ".pmc"
83
p = subprocess.Popen(["pmcstat",
84
"-O", pmcout,
85
"-P", counter, args.program],
86
text=True, stderr=PIPE)
87
result = p.wait()
88
resdir = tmpdir + "/" + program + "-" + counter + ".results"
89
os.makedirs(resdir)
90
p = subprocess.Popen(["pmcstat",
91
"-R", pmcout,
92
"-g"],
93
cwd=resdir,
94
text=True, stderr=PIPE)
95
result = p.wait()
96
gmondir = resdir + "/" + counter
97
if Path(gmondir).is_dir():
98
with open(gmondir + "/" + "gprof.out", "w") as file:
99
p = subprocess.Popen(["gprof",
100
args.program,
101
program + ".gmon"],
102
cwd=gmondir,
103
text=True,
104
stdout=file,
105
stderr=subprocess.STDOUT)
106
result = p.wait()
107
else:
108
print ("Failed to get gmon data for ", counter)
109
print(result)
110
111
else:
112
p = subprocess.Popen(["pmcstat", "-p", counter, args.program],
113
text=True, stderr=PIPE)
114
result = p.wait()
115
print(result)
116
if (args.wait == True):
117
try:
118
value = input("Waitin for you to press ENTER")
119
except EOFError:
120
sys.exit()
121
122
# The canonical way to make a python module into a script.
123
# Remove if unnecessary.
124
125
if __name__ == "__main__":
126
main()
127
128