Skip to content

Commit

Permalink
[GR-51382] Compute max-rss from the 99th percentile of rss
Browse files Browse the repository at this point in the history
PullRequest: mx/1784
  • Loading branch information
Andrija Kolic committed Apr 11, 2024
2 parents 508df94 + bbc383d commit 5588b93
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/mx/_impl/mx.py
Original file line number Diff line number Diff line change
Expand Up @@ -18147,7 +18147,7 @@ def alarm_handler(signum, frame):
_CACHE_DIR = get_env('MX_CACHE_DIR', join(dot_mx_dir(), 'cache'))

# The version must be updated for every PR (checked in CI) and the comment should reflect the PR's issue
version = VersionSpec("7.22.1") # [GR-53101] Remove possibility of having a list of trackers
version = VersionSpec("7.22.2") # [GR-51382] Replace maxrss in favor of rsspercentiles as the default tracker

_mx_start_datetime = datetime.utcnow()

Expand Down
57 changes: 50 additions & 7 deletions src/mx/_impl/mx_benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@
from argparse import SUPPRESS
from collections import OrderedDict
from typing import Callable, Sequence, Iterable, NoReturn, Optional, Dict, Any, List, Collection
from .support.logging import log_deprecation

from . import mx

Expand Down Expand Up @@ -2726,6 +2727,10 @@ def get_rules(self, bmSuiteArgs):
raise NotImplementedError()

class RssTracker(Tracker):
def __init__(self, bmSuite):
super().__init__(bmSuite)
log_deprecation("The 'rss' tracker is deprecated, use 'rsspercentiles' instead!")

def map_command(self, cmd):
"""
Tracks the max resident memory size used by the process using the 'time' command.
Expand Down Expand Up @@ -2891,10 +2896,12 @@ class RssPercentilesTracker(Tracker):
# the time period between two polls, in seconds
poll_interval = 0.1

def __init__(self, bmSuite, skip=0):
def __init__(self, bmSuite, skip=0, copy_into_max_rss=True):
super().__init__(bmSuite)
self.most_recent_text_output = None
self.skip = skip # the number of RSS entries to skip from each poll (used to skip entries of other trackers)
self.copy_into_max_rss = copy_into_max_rss
self.percentile_data_points = []

def map_command(self, cmd):
if not _use_tracker:
Expand All @@ -2908,6 +2915,7 @@ def map_command(self, cmd):
bench_name = self.bmSuite.currently_running_benchmark() if self.bmSuite else "benchmark"
if self.bmSuite:
bench_name = f"{self.bmSuite.name()}-{bench_name}"
bench_name = bench_name.replace("/", "-")
ts = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
text_output = os.path.join(os.getcwd(), f"ps_{bench_name}_{ts}.txt")

Expand All @@ -2916,7 +2924,10 @@ def map_command(self, cmd):
return ["python3", ps_poller_script_path, "-f", text_output, "-i", str(RssPercentilesTracker.poll_interval)] + cmd

def get_rules(self, bmSuiteArgs):
return [RssPercentilesTracker.RssPercentilesRule(self, bmSuiteArgs)]
if self.copy_into_max_rss:
return [RssPercentilesTracker.RssPercentilesRule(self, bmSuiteArgs), RssPercentilesTracker.MaxRssCopyRule(self, bmSuiteArgs)]
else:
return [RssPercentilesTracker.RssPercentilesRule(self, bmSuiteArgs)]

class RssPercentilesRule(CSVBaseRule):
def __init__(self, tracker, bmSuiteArgs, **kwargs):
Expand Down Expand Up @@ -2986,17 +2997,49 @@ def pc(k): # k-percentile with linear interpolation between closest ranks
v = v / 1024 # convert to MB
return {"metric_percentile": str(k), "metric_value": str(int(v))}

percentiles = [pc(perc) for perc in RssPercentilesTracker.interesting_percentiles]
for rss_percentile in percentiles:
self.tracker.percentile_data_points = [pc(perc) for perc in RssPercentilesTracker.interesting_percentiles]
for rss_percentile in self.tracker.percentile_data_points:
mx.log(f"\t{rss_percentile['metric_percentile']}th RSS percentile (MB): {rss_percentile['metric_value']}")
return percentiles
return self.tracker.percentile_data_points

class MaxRssCopyRule(BaseRule):
percentile_to_copy_into_max_rss = 99

def __init__(self, tracker, bmSuiteArgs):
replacement = {
"benchmark": tracker.bmSuite.currently_running_benchmark(),
"bench-suite": tracker.bmSuite.benchSuiteName(bmSuiteArgs) if mx_benchmark_compatibility().bench_suite_needs_suite_args() else tracker.bmSuite.benchSuiteName(),
"config.vm-flags": ' '.join(tracker.bmSuite.vmArgs(bmSuiteArgs)),
"metric.name": "max-rss",
"metric.value": ("<metric_value>", int),
"metric.unit": "MB",
"metric.type": "numeric",
"metric.score-function": "id",
"metric.better": "lower",
"metric.iteration": 0
}
super().__init__(replacement)
self.tracker = tracker

def parseResults(self, text):
for rss_dp in self.tracker.percentile_data_points:
if rss_dp['metric_percentile'] == str(RssPercentilesTracker.MaxRssCopyRule.percentile_to_copy_into_max_rss):
mx.log(f"\n\tmax-rss copied from {rss_dp['metric_percentile']}th RSS percentile (MB): {rss_dp['metric_value']}")
return [{"metric_value": rss_dp['metric_value']}]
mx.warn(f"Couldn't find {RssPercentilesTracker.MaxRssCopyRule.percentile_to_copy_into_max_rss}th RSS percentile to copy into max-rss, metric will be omitted!")
return []


class RssPercentilesAndMaxTracker(Tracker):
def __init__(self, bmSuite):
super().__init__(bmSuite)
self.rss_max_tracker = RssTracker(bmSuite)
self.rss_percentiles_tracker = RssPercentilesTracker(bmSuite, skip=1) # skip RSS of the 'time' command
self.rss_percentiles_tracker = RssPercentilesTracker(
bmSuite,
skip=1, # skip RSS of the 'time' command
copy_into_max_rss=False # don't copy a percentile into max-rss, since the rss_max_tracker will generate the metric
)
log_deprecation("The 'rsspercentiles+maxrss' tracker is deprecated, use 'rsspercentiles' instead!")

def map_command(self, cmd):
return self.rss_percentiles_tracker.map_command(self.rss_max_tracker.map_command(cmd))
Expand Down Expand Up @@ -3288,7 +3331,7 @@ def benchmark(self, mxBenchmarkArgs, bmSuiteArgs, returnSuiteAndResults=False):
parser.add_argument(
"--bench-suite-version", default=None, help="Desired version of the benchmark suite to execute.")
parser.add_argument(
"--tracker", default='rss', help="Enable extra trackers like 'rss' or 'psrecord'. If not set, 'rss' is used.")
"--tracker", default='rsspercentiles', help="Enable extra trackers like 'rsspercentiles', 'rss' or 'psrecord'. If not set, 'rsspercentiles' is used.")
parser.add_argument(
"--machine-name", default=None, help="Abstract name of the target machine.")
parser.add_argument(
Expand Down

0 comments on commit 5588b93

Please sign in to comment.