Skip to content

Commit 906a06a

Browse files
authored
Track and report unpack performance (distributed-system-analysis#3610)
I added a simple server.unpack-perf metadata, which is a JSON block like {"min": <seconds>, "max": <seconds>, "count": <unpack_count>}, and then played with the report generator to get some statistics. I also wrote a report of the Audit table contents to summarize the operations, statuses, and users involved in the Pbench Server. The sample below is for a runlocal, with a few small-ish tarballs. The big catch in deploying this would be that none of the existing datasets will have server.unpack-perf until they're unpacked again, which somewhat reduces the value of the statistics until they get unpacked again (e.g., for TOC or visualize). Cache report: 7 datasets currently unpacked, consuming 51.7 MB 7 datasets have been unpacked a total of 7 times The least recently used cache was referenced today, fio_rw_2018.02.01T22.40.57 The most recently used cache was referenced today, trafficgen_basic-forwarding-example_tg:trex-profile_pf:forwarding_test.json_ml:5_tt:bs__2019-08-27T14:58:38 The smallest cache is 307.2 kB, linpack_mock_2020.02.28T19.10.55 The biggest cache is 19.6 MB, trafficgen_basic-forwarding-example_tg:trex-profile_pf:forwarding_test.json_ml:5_tt:bs__2019-08-27T14:58:38 The worst compression ratio is 22.156%, uperf_rhel8.1_4.18.0-107.el8_snap4_25gb_virt_2019.06.21T01.28.57 The best compression ratio is 96.834%, pbench-user-benchmark_example-vmstat_2018.10.24T14.38.18 The fastest cache unpack is 0.014 seconds, linpack_mock_2020.02.28T19.10.55 The slowest cache unpack is 0.084 seconds, trafficgen_basic-forwarding-example_tg:trex-profile_pf:forwarding_test.json_ml:5_tt:bs__2019-08-27T14:58:38 The fastest cache unpack streaming rate is 233.226 Mb/second, trafficgen_basic-forwarding-example_tg:trex-profile_pf:forwarding_test.json_ml:5_tt:bs__2019-08-27T14:58:38 The slowest cache unpack streaming rate is 22.228 Mb/second, linpack_mock_2020.02.28T19.10.55 1 datasets have no unpacked size, 1 are missing reference timestamps, 0 have bad size metadata 1 datasets are missing unpack metric data, 0 have bad unpack metric data 1 datasets are missing unpack performance data Audit logs: 138 audit log rows for 69 events 0 unterminated root rows, 0 unmatched terminators Status summary: BEGIN 69 SUCCESS 68 FAILURE 1 Operation summary: template 36 upload 9 cache 7 index 6 apikey 1 update 10 Object type summary: TEMPLATE 36 DATASET 32 API_KEY 1 Users summary: BACKGROUND 49 tester 18 testadmin 2
1 parent f8654f3 commit 906a06a

File tree

8 files changed

+527
-235
lines changed

8 files changed

+527
-235
lines changed

lib/pbench/cli/server/__init__.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,129 @@
1+
import datetime
2+
from threading import Thread
3+
import time
4+
5+
import click
6+
17
from pbench.server import PbenchServerConfig
28
from pbench.server.database import init_db
39

410

11+
class Detail:
12+
"""Encapsulate generation of additional diagnostics"""
13+
14+
def __init__(self, detail: bool = False, errors: bool = False):
15+
"""Initialize the object.
16+
17+
Args:
18+
detail: True if detailed messages should be generated
19+
errors: True if individual file errors should be reported
20+
"""
21+
self.detail = detail
22+
self.errors = errors
23+
24+
def __bool__(self) -> bool:
25+
"""Report whether detailed messages are enabled
26+
27+
Returns:
28+
True if details are enabled
29+
"""
30+
return self.detail
31+
32+
def error(self, message: str):
33+
"""Write a message if details are enabled.
34+
35+
Args:
36+
message: Detail string
37+
"""
38+
if self.errors:
39+
click.secho(f"|| {message}", fg="red")
40+
41+
def message(self, message: str):
42+
"""Write a message if details are enabled.
43+
44+
Args:
45+
message: Detail string
46+
"""
47+
if self.detail:
48+
click.echo(f"|| {message}")
49+
50+
51+
class Verify:
52+
"""Encapsulate -v status messages."""
53+
54+
def __init__(self, verify: bool):
55+
"""Initialize the object.
56+
57+
Args:
58+
verify: True to write status messages.
59+
"""
60+
self.verify = verify
61+
62+
def __bool__(self) -> bool:
63+
"""Report whether verification is enabled.
64+
65+
Returns:
66+
True if verification is enabled.
67+
"""
68+
return self.verify
69+
70+
def status(self, message: str):
71+
"""Write a message if verification is enabled.
72+
73+
Args:
74+
message: status string
75+
"""
76+
if self.verify:
77+
ts = datetime.datetime.now().astimezone()
78+
click.secho(f"({ts:%H:%M:%S}) {message}", fg="green")
79+
80+
81+
class Watch:
82+
"""Encapsulate a periodic status update.
83+
84+
The active message can be updated at will; a background thread will
85+
periodically print the most recent status.
86+
"""
87+
88+
def __init__(self, interval: float):
89+
"""Initialize the object.
90+
91+
Args:
92+
interval: interval in seconds for status updates
93+
"""
94+
self.start = time.time()
95+
self.interval = interval
96+
self.status = "starting"
97+
if interval:
98+
self.thread = Thread(target=self.watcher)
99+
self.thread.setDaemon(True)
100+
self.thread.start()
101+
102+
def update(self, status: str):
103+
"""Update status if appropriate.
104+
105+
Update the message to be printed at the next interval, if progress
106+
reporting is enabled.
107+
108+
Args:
109+
status: status string
110+
"""
111+
self.status = status
112+
113+
def watcher(self):
114+
"""A worker thread to periodically write status messages."""
115+
116+
while True:
117+
time.sleep(self.interval)
118+
now = time.time()
119+
delta = int(now - self.start)
120+
hours, remainder = divmod(delta, 3600)
121+
minutes, seconds = divmod(remainder, 60)
122+
click.secho(
123+
f"[{hours:02d}:{minutes:02d}:{seconds:02d}] {self.status}", fg="cyan"
124+
)
125+
126+
5127
def config_setup(context: object) -> PbenchServerConfig:
6128
config = PbenchServerConfig.create(context.config)
7129
# We're going to need the DB to track dataset state, so setup DB access.

lib/pbench/cli/server/options.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@ def _pbench_server_config(f: Callable) -> Callable:
2222

2323
def callback(ctx, param, value):
2424
clictx = ctx.ensure_object(CliContext)
25-
clictx.config = value
25+
clictx.config = (
26+
value if value else "/opt/pbench-server/lib/config/pbench-server.cfg"
27+
)
2628
return value
2729

2830
return click.option(
2931
"-C",
3032
"--config",
31-
required=True,
33+
required=False,
3234
envvar="_PBENCH_SERVER_CONFIG",
3335
type=click.Path(exists=True, readable=True),
3436
callback=callback,

0 commit comments

Comments
 (0)