Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

run without root permission #66

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion perf-collect.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ def supports_psi():
def tma_supported():
perf_out = ""
try:
# run perf stat briefly to determine if these two events are supported
perf = subprocess.Popen(
shlex.split(
"perf stat -a -e '{cpu/event=0x00,umask=0x04,period=10000003,name='TOPDOWN.SLOTS'/,cpu/event=0x00,umask=0x81,period=10000003,name='PERF_METRICS.BAD_SPECULATION'/}' sleep .1"
Expand All @@ -170,9 +171,11 @@ def tma_supported():
)
perf_out = perf.communicate()[0].decode()
except subprocess.CalledProcessError:
logging.info("perf stat exited with error while checking for TMA support")
return False

try:
# create a dictionary of perf events and their counts from perf stat output
events = {
a.split()[1]: int(a.split()[0].replace(",", ""))
for a in filter(
Expand All @@ -181,10 +184,17 @@ def tma_supported():
)
}
except Exception:
logging.info("error parsing perf stat output while checking for TMA support")
return False

# This is a perf artifact of no vPMU support
if events["TOPDOWN.SLOTS"] == events["PERF_METRICS.BAD_SPECULATION"]:
logging.info("TOPDOWN.SLOTS and PERF_METRICS.BAD_SPECULATION counts are equal")
return False

# A zero value on either of these metrics is an indication that the TMA events are not supported
if events["TOPDOWN.SLOTS"] == 0 or events["PERF_METRICS.BAD_SPECULATION"] == 0:
logging.info("TOPDOWN.SLOTS or PERF_METRICS.BAD_SPECULATION count is zero")
return False

return True
Expand Down Expand Up @@ -295,7 +305,9 @@ def validate_file(fname):
sys.exit()

if os.geteuid() != 0:
crash("Must run PerfSpect as root, please re-run")
logging.warning(
"PerfSpect requires elevated permissions to run. User is not root. Proceeding anyway..."
)

# disable nmi watchdog before collecting perf
nmi_watchdog = perf_helpers.disable_nmi_watchdog()
Expand Down
28 changes: 17 additions & 11 deletions src/perf_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,9 @@ def disable_nmi_watchdog():
proc_output = subprocess.check_output(["cat", "/proc/sys/kernel/nmi_watchdog"])
nmi_watchdog_status = int(proc_output.decode().strip())
if nmi_watchdog_status == 1:
proc_output = subprocess.check_output(["sysctl", "kernel.nmi_watchdog=0"])
proc_output = subprocess.check_output(
["sysctl", "kernel.nmi_watchdog=0"], stderr=subprocess.STDOUT
)
new_watchdog_status = int(
proc_output.decode().strip().replace("kernel.nmi_watchdog = ", "")
)
Expand All @@ -158,7 +160,7 @@ def disable_nmi_watchdog():
logging.info("nmi_watchdog already disabled. No change needed.")
return nmi_watchdog_status
except (ValueError, FileNotFoundError, subprocess.CalledProcessError) as e:
crash(f"Failed to disable nmi_watchdog: {e}")
logging.warning(f"Failed to disable nmi_watchdog: {e}")


# enable nmi watchdog
Expand All @@ -183,15 +185,19 @@ def set_perf_event_mux_interval(reset, interval_ms, mux_interval):
if os.path.isdir(dirpath):
muxfile = os.path.join(dirpath, "perf_event_mux_interval_ms")
if os.path.isfile(muxfile):
with open(muxfile, "w") as f_mux:
val = 0
if reset:
val = int(mux_interval[f])
else:
if int(mux_interval[f]):
val = int(interval_ms)
if val:
f_mux.write(str(val))
try:
with open(muxfile, "w") as f_mux:
val = 0
if reset:
val = int(mux_interval[f])
else:
if int(mux_interval[f]):
val = int(interval_ms)
if val:
f_mux.write(str(val))
except OSError as e:
logging.warning(f"Failed to write mux interval: {e}")
break


# get linux kernel version
Expand Down
4 changes: 2 additions & 2 deletions src/prepare_perf_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ def is_cpu_event(line):
if (
(len(tmp_list) == 1 or tmp_list[0] == "cpu" or tmp_list[0].startswith("cstate"))
and "OCR." not in line
and "uops_retired.ms" not in line
and "int_misc.unknown_branch_cycles" not in line
and "uops_retired.ms" not in line.lower()
and "int_misc.unknown_branch_cycles" not in line.lower()
and "power/" not in line
):
return True
Expand Down
Loading