Skip to content

Commit

Permalink
Avoid checking for time binary more than once and don't show progress…
Browse files Browse the repository at this point in the history
… update in execution plan (#231)
  • Loading branch information
smarr committed Jul 31, 2023
2 parents 0b4936c + ba345a4 commit 4f059a3
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 24 deletions.
29 changes: 16 additions & 13 deletions rebench/executor.py
Expand Up @@ -43,7 +43,8 @@ def __init__(self, name, build_command):

class RunScheduler(object):

def __init__(self, executor, ui):
def __init__(self, executor, ui, print_execution_plan):
self._print_execution_plan = print_execution_plan
self._executor = executor
self.ui = ui
self._runs_completed = 0
Expand Down Expand Up @@ -74,7 +75,7 @@ def _estimate_time_left(self):
return floor(hour), floor(minute), floor(sec)

def _indicate_progress(self, completed_task, run):
if not self.ui.spinner_initialized():
if not self.ui.spinner_initialized() or self._print_execution_plan:
return

if completed_task:
Expand All @@ -101,7 +102,8 @@ def execute(self):
self._runs_completed = completed_runs

with self.ui.init_spinner(self._total_num_runs):
self.ui.step_spinner(completed_runs)
if not self._print_execution_plan:
self.ui.step_spinner(completed_runs)
self._process_remaining_runs(runs)


Expand Down Expand Up @@ -196,8 +198,8 @@ def __init__(self, exceptions):

class ParallelScheduler(RunScheduler):

def __init__(self, executor, seq_scheduler_class, ui):
RunScheduler.__init__(self, executor, ui)
def __init__(self, executor, seq_scheduler_class, ui, print_execution_plan):
RunScheduler.__init__(self, executor, ui, print_execution_plan)
self._seq_scheduler_class = seq_scheduler_class
self._lock = RLock()
self._num_worker_threads = self._number_of_threads()
Expand All @@ -223,7 +225,7 @@ def _split_runs(runs):
def _process_sequential_runs(self, runs):
seq_runs, par_runs = self._split_runs(runs)

scheduler = self._seq_scheduler_class(self._executor, self.ui)
scheduler = self._seq_scheduler_class(self._executor, self.ui, self._print_execution_plan)
scheduler._process_remaining_runs(seq_runs)

return par_runs
Expand Down Expand Up @@ -257,7 +259,7 @@ def _determine_num_work_items_to_take(self):
return per_thread

def get_local_scheduler(self):
return self._seq_scheduler_class(self._executor, self.ui)
return self._seq_scheduler_class(self._executor, self.ui, self._print_execution_plan)

def acquire_work(self):
with self._lock:
Expand All @@ -279,20 +281,20 @@ def __init__(self, runs, do_builds, ui, include_faulty=False,
artifact_review=False, use_nice=False, use_shielding=False,
print_execution_plan=False, config_dir=None,
use_denoise=True):
self.use_denoise=use_denoise
self.use_denoise = use_denoise
self._runs = runs

self._use_nice = use_nice
self._use_shielding = use_shielding
self.use_denoise = self.use_denoise and (use_nice or use_shielding)
self.use_denoise = self.use_denoise and (use_nice or use_shielding)

self._print_execution_plan = print_execution_plan

self._do_builds = do_builds
self.ui = ui
self._include_faulty = include_faulty
self.debug = debug
self._scheduler = self._create_scheduler(scheduler)
self._scheduler = self._create_scheduler(scheduler, print_execution_plan)
self.build_log = build_log
self._artifact_review = artifact_review
self.config_dir = config_dir
Expand All @@ -301,17 +303,17 @@ def __init__(self, runs, do_builds, ui, include_faulty=False,
for run in runs:
run.set_total_number_of_runs(num_runs)

def _create_scheduler(self, scheduler):
def _create_scheduler(self, scheduler, print_execution_plan):
# figure out whether to use parallel scheduler
if cpu_count() > 1:
i = 0
for run in self._runs:
if not run.execute_exclusively:
i += 1
if i > 1:
return ParallelScheduler(self, scheduler, self.ui)
return ParallelScheduler(self, scheduler, self.ui, print_execution_plan)

return scheduler(self, self.ui)
return scheduler(self, self.ui, print_execution_plan)

def _construct_cmdline(self, run_id, gauge_adapter):
cmdline = ""
Expand Down Expand Up @@ -490,6 +492,7 @@ def _get_gauge_adapter_instance(self, run_id):

def _generate_data_point(self, cmdline, gauge_adapter, run_id,
termination_check):
assert not self._print_execution_plan
# execute the external program here
output = ""
try:
Expand Down
36 changes: 25 additions & 11 deletions rebench/interop/time_adapter.py
Expand Up @@ -38,38 +38,52 @@ class TimeAdapter(GaugeAdapter):
re_formatted_time = re.compile(r"^wall-time \(secounds\): (\d+\.\d+)")
re_formatted_rss = re.compile(r"^max rss \(kb\): (\d+)")

_completed_time_availability_check = False
_use_formatted_time = False
_time_bin = None

def __init__(self, include_faulty, executor):
GaugeAdapter.__init__(self, include_faulty, executor)
self._use_formatted_time = False

def _create_command(self, command):
assert self._completed_time_availability_check
if self._use_formatted_time:
return "%s -f %s %s" % (self._time_bin, TimeAdapter.time_format, command)
else:
# use standard, but without info on memory
# TODO: add support for reading out memory info on OS X
return "/usr/bin/time -p %s" % command

def acquire_command(self, run_id):
command = run_id.cmdline()
time_bin = '/usr/bin/time'

if not self._completed_time_availability_check:
self._check_which_time_command_is_available()

return self._create_command(command)

def _check_which_time_command_is_available(self):
time_bin = '/usr/bin/time'
try:
formatted_output = subprocess.call(
['/usr/bin/time', '-f', TimeAdapter.time_format, '/bin/sleep', '1'],
['/usr/bin/time', '-f', TimeAdapter.time_format, '/bin/sleep', '0'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except OSError:
formatted_output = 1

if formatted_output == 1:
try:
formatted_output = subprocess.call(
['/opt/local/bin/gtime', '-f', TimeAdapter.time_format, '/bin/sleep', '1'],
['/opt/local/bin/gtime', '-f', TimeAdapter.time_format, '/bin/sleep', '0'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if formatted_output == 0:
time_bin = '/opt/local/bin/gtime'
except OSError:
formatted_output = 1

if formatted_output == 0:
self._use_formatted_time = True
return "%s -f %s %s" % (time_bin, TimeAdapter.time_format, command)
else:
# use standard, but without info on memory
# TODO: add support for reading out memory info on OS X
return "/usr/bin/time -p %s" % command
TimeAdapter._use_formatted_time = formatted_output == 0
TimeAdapter._time_bin = time_bin
TimeAdapter._completed_time_availability_check = True

def parse_data(self, data, run_id, invocation):
iteration = 1
Expand Down
1 change: 1 addition & 0 deletions rebench/tests/interop/time_adapter_test.py
Expand Up @@ -40,6 +40,7 @@ def test_parse_data(self):
user 5.00
sys 1.00"""
adapter = TimeAdapter(False, None)
TimeAdapter._use_formatted_time = False
data = adapter.parse_data(data, None, 1)
self.assertEqual(1, len(data))

Expand Down

0 comments on commit 4f059a3

Please sign in to comment.