-
Notifications
You must be signed in to change notification settings - Fork 96
CPU and Max RSS Analysis tools #6663
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
base: master
Are you sure you want to change the base?
Changes from all commits
246a4c1
9727be9
171f7ee
7d50d0b
8608088
060056b
a0cdcd6
3d4a187
3057edd
a6ecd29
e5119b4
9f593fc
5f84c2f
47a4a98
356abff
6ed1770
4cfcffe
1e5b804
38c31f5
339af9c
391559b
b9c080c
7091711
ad6b3a1
5bddeef
afcdd81
378dcb9
ca1e796
58fae4f
64e9b2b
07348b7
b485fd7
5793b23
73545ac
bf1b9c9
30d4382
49fcbc8
c63a250
939e128
4928405
66acd1f
935fdc6
cacf077
99f9ae5
a542523
1a63365
048606b
b05c38d
80963cd
5d3cb0c
f51794b
27a0879
6efc7cf
9a5a4fa
5a620ed
f43bd83
8f7c419
6f8c3f3
2e02286
2923917
ce4122b
15c29fa
c09aa6f
a29cf82
172b453
59200fc
35daea9
9189ac3
31f2c18
baaa1a6
038348a
2975ea4
0448e70
3cff4a1
c8f3ab5
5e994fb
5c8585e
0c68cec
7eddcf2
2cd9991
c1a5686
2bc9ec6
8ca760d
ebbb8f0
6f65ebd
54553c1
556f3ba
f70c1d3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -58,4 +58,5 @@ github-actions[bot] <[email protected]> | |
github-actions[bot] <[email protected]> GitHub Action | ||
Diquan Jabbour <[email protected]> | ||
Maxime Rio <[email protected]> | ||
Christopher Bennett <[email protected]> ChrisPaulBennett <[email protected]> | ||
Christopher Bennett <[email protected]> christopher.bennett <[email protected]> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Adding CPU time and Max RSS to Analysis Tools |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -139,6 +139,12 @@ cylc__job__main() { | |||||
mkdir -p "$(dirname "${CYLC_TASK_WORK_DIR}")" || true | ||||||
mkdir -p "${CYLC_TASK_WORK_DIR}" | ||||||
cd "${CYLC_TASK_WORK_DIR}" | ||||||
|
||||||
if [[ "${CYLC_PROFILE}" == "True" ]] ; then | ||||||
cylc profile -m "${CYLC_CGROUP}" -i "${CYLC_POLLING_INTERVAL}" & | ||||||
export profiler_pid="$!" | ||||||
fi | ||||||
|
||||||
# Env-Script, User Environment, Pre-Script, Script and Post-Script | ||||||
# Run user scripts in subshell to protect cylc job script from interference. | ||||||
# Waiting on background process allows signal traps to trigger immediately. | ||||||
|
@@ -157,11 +163,15 @@ cylc__job__main() { | |||||
cylc__set_return "$ret_code" | ||||||
fi | ||||||
} | ||||||
# Grab the max rss and cpu_time and clean up before changing directory | ||||||
cylc__kill_profiler | ||||||
# Empty work directory remove | ||||||
cd | ||||||
rmdir "${CYLC_TASK_WORK_DIR}" 2>'/dev/null' || true | ||||||
# Send task succeeded message | ||||||
|
||||||
wait "${CYLC_TASK_MESSAGE_STARTED_PID}" 2>'/dev/null' || true | ||||||
|
||||||
cylc message -- "${CYLC_WORKFLOW_ID}" "${CYLC_TASK_JOB}" 'succeeded' || true | ||||||
# (Ignore shellcheck "globbing and word splitting" warning here). | ||||||
# shellcheck disable=SC2086 | ||||||
|
@@ -187,6 +197,14 @@ cylc__set_return() { | |||||
return "${1:-0}" | ||||||
} | ||||||
|
||||||
############################################################################### | ||||||
# Save the data using cylc message and exit the profiler | ||||||
cylc__kill_profiler() { | ||||||
if [[ -n "${profiler_pid:-}" && -d "/proc/${profiler_pid}" ]]; then | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The POSIX standard is a set of interfaces that all compliant operating systems must follow (Mac OS included). The The most POSIX way to determine if a process is running that I could find is
Suggested change
You can see the POSIX description for the https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ps.html The index of commands is here: |
||||||
kill -s SIGINT "${profiler_pid}" || true | ||||||
fi | ||||||
} | ||||||
|
||||||
############################################################################### | ||||||
# Disable selected or all (if no arguments given) fail traps. | ||||||
# Globals: | ||||||
|
@@ -268,6 +286,9 @@ cylc__job_finish_err() { | |||||
# (Ignore shellcheck "globbing and word splitting" warning here). | ||||||
# shellcheck disable=SC2086 | ||||||
trap '' ${CYLC_VACATION_SIGNALS:-} ${CYLC_FAIL_SIGNALS} | ||||||
|
||||||
cylc__kill_profiler | ||||||
ChrisPaulBennett marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
|
||||||
if [[ -n "${CYLC_TASK_MESSAGE_STARTED_PID:-}" ]]; then | ||||||
wait "${CYLC_TASK_MESSAGE_STARTED_PID}" 2>'/dev/null' || true | ||||||
fi | ||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,236 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#!/usr/bin/env python3 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# THIS FILE IS PART OF THE CYLC WORKFLOW ENGINE. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Copyright (C) NIWA & British Crown (Met Office) & Contributors. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# This program is free software: you can redistribute it and/or modify | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# it under the terms of the GNU General Public License as published by | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# the Free Software Foundation, either version 3 of the License, or | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# (at your option) any later version. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# This program is distributed in the hope that it will be useful, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# GNU General Public License for more details. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# You should have received a copy of the GNU General Public License | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"""cylc profiler [OPTIONS] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Profiler which periodically polls cgroups to track | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
the resource usage of jobs running on the node. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import os | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import re | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import sys | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import time | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import signal | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import asyncio | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from pathlib import Path | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from dataclasses import dataclass | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from cylc.flow.terminal import cli_function | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from cylc.flow.network.client_factory import get_client | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from cylc.flow.option_parsers import CylcOptionParser as COP | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
INTERNAL = True | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PID_REGEX = re.compile(r"([^:]*\d{6,}.*)") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
RE_INT = re.compile(r'\d+') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
max_rss_location = None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cpu_time_location = None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cgroup_version = None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
comms_timeout = None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+38
to
+41
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unused global variables:
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def get_option_parser() -> COP: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
parser = COP( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
__doc__, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
comms=True, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
argdoc=[ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
parser.add_option( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"-i", type=int, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
help="interval between query cycles in seconds", dest="delay") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
parser.add_option( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"-m", type=str, help="Location of cgroups directory", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
dest="cgroup_location") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return parser | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@cli_function(get_option_parser) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def main(parser: COP, options) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"""CLI main.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
global comms_timeout | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Register the stop_profiler function with the signal library | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
signal.signal(signal.SIGINT, stop_profiler) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
signal.signal(signal.SIGHUP, stop_profiler) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
signal.signal(signal.SIGTERM, stop_profiler) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
comms_timeout = options.comms_timeout | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+64
to
+70
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unused global variables:
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
get_config(options) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@dataclass | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
class Process: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"""Class for representing CPU and Memory usage of a process""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cgroup_memory_path: str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cgroup_cpu_path: str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def stop_profiler(*args): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"""This function will be executed when the SIGINT signal is sent | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
to this process""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# If a task fails instantly, or finishes very quickly (< 1 second), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# the get config function doesn't have time to run | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (max_rss_location is None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
or cpu_time_location is None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
or cgroup_version is None): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
max_rss = 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cpu_time = 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
max_rss = parse_memory_file(max_rss_location) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cpu_time = parse_cpu_file(cpu_time_location, cgroup_version) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GRAPHQL_MUTATION = """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mutation($WORKFLOWS: [WorkflowID]!, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$MESSAGES: [[String]], $JOB: String!, $TIME: String) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
message(workflows: $WORKFLOWS, messages:$MESSAGES, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
taskJob:$JOB, eventTime:$TIME) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
result | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GRAPHQL_REQUEST_VARIABLES = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"WORKFLOWS": [os.environ.get('CYLC_WORKFLOW_ID')], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"MESSAGES": [["DEBUG", f"cpu_time {cpu_time} max_rss {max_rss}"]], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"JOB": os.environ.get('CYLC_TASK_JOB'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"TIME": "now" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pclient = get_client(os.environ.get('CYLC_WORKFLOW_ID'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
timeout=comms_timeout) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
async def send_cylc_message(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
await pclient.async_request( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'graphql', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{'request_string': GRAPHQL_MUTATION, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'variables': GRAPHQL_REQUEST_VARIABLES}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
asyncio.run(send_cylc_message()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sys.exit(0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def parse_memory_file(cgroup_memory_path): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"""Open the memory stat file and copy the appropriate data""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
with open(cgroup_memory_path, 'r') as f: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for line in f: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return int(line) // 1024 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def parse_cpu_file(cgroup_cpu_path, cgroup_version): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"""Open the memory stat file and return the appropriate data""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if cgroup_version == 2: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
with open(cgroup_cpu_path, 'r') as f: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for line in f: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if "usage_usec" in line: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return int(RE_INT.findall(line)[0]) // 1000 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
elif cgroup_version == 1: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
with open(cgroup_cpu_path, 'r') as f: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for line in f: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Cgroups v2 uses nanoseconds | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return int(line) / 1000000 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def get_cgroup_version(cgroup_location: str, cgroup_name: str) -> int: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# HPC uses cgroups v2 and SPICE uses cgroups v1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
global cgroup_version | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if Path.exists(Path(cgroup_location + cgroup_name)): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cgroup_version = 2 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return cgroup_version | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
elif Path.exists(Path(cgroup_location + "/memory" + cgroup_name)): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cgroup_version = 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return cgroup_version | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
raise FileNotFoundError("Cgroup not found at " + | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cgroup_location + cgroup_name) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+151
to
+161
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unused global variables: (also Met Office specific comment)
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def get_cgroup_name(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"""Get the cgroup directory for the current process""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# fugly hack to allow functional tests to use test data | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤣 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if 'profiler_test_env_var' in os.environ: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return os.getenv('profiler_test_env_var') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Get the PID of the current process | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pid = os.getpid() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
try: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Get the cgroup information for the current process | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
with open('/proc/' + str(pid) + '/cgroup', 'r') as f: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
result = f.read() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
result = PID_REGEX.search(result).group() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return result | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
except FileNotFoundError as err: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
raise FileNotFoundError( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'/proc/' + str(pid) + '/cgroup not found') from err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
except AttributeError as err: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
raise AttributeError("No cgroup found for process:", pid) from err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def get_cgroup_paths(version, location, name): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
global max_rss_location | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
global cpu_time_location | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if version == 2: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
max_rss_location = location + name + "/" + "memory.peak" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cpu_time_location = location + name + "/" + "cpu.stat" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return Process( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cgroup_memory_path=location + | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
name + "/" + "memory.peak", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cgroup_cpu_path=location + | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
name + "/" + "cpu.stat") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
elif version == 1: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
max_rss_location = (location + "/memory" + | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
name + "/memory.max_usage_in_bytes") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cpu_time_location = (location + "/cpu" + | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
name + "/cpuacct.usage") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return Process( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cgroup_memory_path=location + "/memory" + | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
name + "/memory.max_usage_in_bytes", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cgroup_cpu_path=location + "/cpu" + | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
name + "/cpuacct.usage") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+188
to
+208
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unused global variables:
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These global variables are used. They are used in the stop_profiler function. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def profile(process, version, delay, keep_looping=lambda: True): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# The infinite loop that will constantly poll the cgroup | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# The lambda function is used to allow the loop to be stopped in unit tests | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
while keep_looping(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Write cpu / memory usage data to disk | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# CPU_TIME = parse_cpu_file(process.cgroup_cpu_path, version) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
time.sleep(delay) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
def get_config(args): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Find the cgroup that this process is running in. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Cylc will put this profiler in the same cgroup | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# as the job it is profiling | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cgroup_name = get_cgroup_name() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cgroup_version = get_cgroup_version(args.cgroup_location, cgroup_name) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
process = get_cgroup_paths(cgroup_version, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
args.cgroup_location, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
cgroup_name) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
profile(process, cgroup_version, args.delay) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if __name__ == "__main__": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
arg_parser = get_option_parser() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
get_config(arg_parser.parse_args([])) |
Uh oh!
There was an error while loading. Please reload this page.