Skip to content

Commit a833224

Browse files
authored
Make hooks work in bench_command subprocesses (#197)
* Make hooks work in bench_command subprocesses * Fix tests
1 parent bff934a commit a833224

File tree

4 files changed

+58
-15
lines changed

4 files changed

+58
-15
lines changed

pyperf/_command.py

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import functools
2+
import json
23
import os.path
34
import subprocess
45
import sys
@@ -23,18 +24,22 @@ def bench_command(command, task, loops):
2324
% proc.returncode)
2425

2526
rss = None
27+
metadata = {}
2628
try:
2729
lines = output.splitlines()
2830
timing = float(lines[0])
29-
if len(lines) >= 2:
30-
rss = int(lines[1])
31+
rss = int(lines[1])
32+
metadata = json.loads(lines[2])
3133
except ValueError:
3234
raise ValueError("failed to parse script output: %r" % output)
3335

34-
if rss:
36+
if rss and rss > 0:
3537
# store the maximum
3638
max_rss = task.metadata.get('command_max_rss', 0)
3739
task.metadata['command_max_rss'] = max(max_rss, rss)
40+
41+
task.metadata.update(metadata)
42+
3843
return timing
3944

4045

pyperf/_hooks.py

+13
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,19 @@ def get_selected_hooks(hook_names):
3131
yield hook_mapping[hook_name]
3232

3333

34+
def instantiate_selected_hooks(hook_names):
35+
hook_managers = {}
36+
for hook in get_selected_hooks(hook_names):
37+
try:
38+
hook_managers[hook.name] = hook.load()()
39+
except HookError as e:
40+
print(f"ERROR setting up hook '{hook.name}':", file=sys.stderr)
41+
print(str(e), file=sys.stderr)
42+
sys.exit(1)
43+
44+
return hook_managers
45+
46+
3447
class HookError(Exception):
3548
pass
3649

pyperf/_process_time.py

+35-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
If resource.getrusage() is available: compute the maximum RSS memory in bytes
1515
per process and writes it into stdout as a second line.
1616
"""
17+
import contextlib
18+
import json
1719
import os
1820
import subprocess
1921
import sys
@@ -91,6 +93,27 @@ def bench_process(loops, args, kw, profile_filename=None):
9193
return (dt, max_rss)
9294

9395

96+
def load_hooks(metadata):
97+
hook_names = []
98+
while "--hook" in sys.argv:
99+
hook_idx = sys.argv.index("--hook")
100+
hook_name = sys.argv[hook_idx + 1]
101+
hook_names.append(hook_name)
102+
del sys.argv[hook_idx]
103+
del sys.argv[hook_idx]
104+
105+
if len(hook_names):
106+
# Only import pyperf if we know we have hooks
107+
import pyperf._hooks
108+
109+
hook_managers = pyperf._hooks.instantiate_selected_hooks(hook_names)
110+
metadata["hooks"] = ", ".join(hook_managers.values())
111+
else:
112+
hook_managers = {}
113+
114+
return hook_managers
115+
116+
94117
def main():
95118
# Make sure that the pyperf module wasn't imported
96119
if 'pyperf' in sys.modules:
@@ -111,6 +134,9 @@ def main():
111134
else:
112135
profile_filename = None
113136

137+
metadata = {}
138+
hook_managers = load_hooks(metadata)
139+
114140
loops = int(sys.argv[1])
115141
args = sys.argv[2:]
116142

@@ -125,15 +151,21 @@ def main():
125151
kw['stdout'] = devnull
126152
kw['stderr'] = subprocess.STDOUT
127153

128-
dt, max_rss = bench_process(loops, args, kw, profile_filename)
154+
with contextlib.ExitStack() as stack:
155+
for hook in hook_managers.values():
156+
stack.enter_context(hook)
157+
dt, max_rss = bench_process(loops, args, kw, profile_filename)
129158

130159
if devnull is not None:
131160
devnull.close()
132161

162+
for hook in hook_managers.values():
163+
hook.teardown(metadata)
164+
133165
# Write timing in seconds into stdout
134166
print(dt)
135-
if max_rss:
136-
print(max_rss)
167+
print(max_rss or -1)
168+
print(json.dumps(metadata))
137169

138170

139171
if __name__ == "__main__":

pyperf/_worker.py

+2-9
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import pyperf
77
from pyperf._formatter import (format_number, format_value, format_values,
88
format_timedelta)
9-
from pyperf._hooks import get_selected_hooks, HookError
9+
from pyperf._hooks import instantiate_selected_hooks
1010
from pyperf._utils import MS_WINDOWS, MAC_OS, percentile, median_abs_dev
1111

1212

@@ -60,14 +60,7 @@ def _compute_values(self, values, nvalue,
6060

6161
task_func = self.task_func
6262

63-
hook_managers = {}
64-
for hook in get_selected_hooks(args.hook):
65-
try:
66-
hook_managers[hook.name] = hook.load()()
67-
except HookError as e:
68-
print(f"ERROR setting up hook '{hook.__name__}:'", file=sys.stderr)
69-
print(str(e), file=sys.stderr)
70-
sys.exit(1)
63+
hook_managers = instantiate_selected_hooks(args.hook)
7164
if len(hook_managers):
7265
self.metadata["hooks"] = ", ".join(hook_managers.keys())
7366

0 commit comments

Comments
 (0)