Skip to content

Commit c95da98

Browse files
Merge branch 'scalability/latency_failure_rate_exp1_query' into 'master'
More plots for query system baseline experiment * Show failure rate and latency for system baseline query experiment, to better judge if there has been a regression. * More iterations for large memory update benchmark * Don't show Xnet benchmark any more (has been broken for a while) See merge request dfinity-lab/public/ic!11137
2 parents a9fd914 + 14f1d7f commit c95da98

File tree

5 files changed

+171
-94
lines changed

5 files changed

+171
-94
lines changed

gitlab-ci/config/60--benchmark-test--spawn-benchmark-pipeline.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ maximum-capacity-large-memory-update:
158158
$SHELL_WRAPPER timeout 1h ./testnet/tools/icos_deploy.sh $TESTNET --git-revision "$GIT_REVISION" --no-boundary-nodes
159159
cd ./scalability
160160
161-
$SHELL_WRAPPER python3 experiments/run_large_memory_experiment.py --testnet $TESTNET --wg_subnet 2 --wg_testnet $TESTNET --use_updates=True --initial_rps=10 --increment_rps=3 --target_rps=25 --max_rps=500
161+
$SHELL_WRAPPER python3 experiments/run_large_memory_experiment.py --testnet $TESTNET --wg_subnet 2 --wg_testnet $TESTNET --use_updates=True --datapoints=20,35,50,55,100,150
162162
163163
TIMESTAMP=$(find results/"$GIT_REVISION" -maxdepth 1 -mindepth 1 -type d -printf "%f\n" | sort -nr | head -1)
164164
$SHELL_WRAPPER python3 common/generate_report.py --base_dir="results/" --git_revision="$GIT_REVISION" --timestamp="$TIMESTAMP"

scalability/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
ii/canister_id
22
ii/.dfx
3+
.dfx/ic/canisters/

scalability/common/cdweekly_results.py

Lines changed: 110 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222

2323
FLAGS = gflags.FLAGS
2424
gflags.DEFINE_string("experiment_data", ".", "Path to experiment data")
25-
gflags.DEFINE_string("asset_root", "", "Path to the root of the asset canister")
26-
gflags.DEFINE_integer("num_boundary_nodes", -1, "Number of boundary nodes in the IC")
25+
gflags.DEFINE_string(
26+
"asset_root", "", "Path to the root of the asset canister")
27+
gflags.DEFINE_integer("num_boundary_nodes", -1,
28+
"Number of boundary nodes in the IC")
2729
gflags.DEFINE_boolean("regenerate", False, "Regenerate all reports")
2830

2931
TEMPLATE_BASEDIR = "templates"
@@ -51,6 +53,7 @@
5153
("c610c3fec6ea8acd1b831099317cc0b98fe4b310", "1649613136"),
5254
("b0d3c45e14b116f8213ed88dea064fbc631c038c", "1667834847"),
5355
("903c8b3a520c69a953b4cdf6468bf2612e86be49", "1660642902"),
56+
("2a0ff6c34e61d64e6fe8b0ce47e7edbec30e8c1e", "1674507377"),
5457
]
5558

5659

@@ -112,7 +115,8 @@ def copy_results(git_revision: str, timestamp: str):
112115
"""Copy results for an individual experiment to the asset canister."""
113116
if len(FLAGS.asset_root) > 0:
114117

115-
source_dir = os.path.join(FLAGS.experiment_data, git_revision, timestamp)
118+
source_dir = os.path.join(
119+
FLAGS.experiment_data, git_revision, timestamp)
116120
target_dir = os.path.join(FLAGS.asset_root, git_revision, timestamp)
117121

118122
# Search for svg files in the iteration folders
@@ -125,20 +129,17 @@ def copy_results(git_revision: str, timestamp: str):
125129
shutil.copy(svg, svg_target_dir)
126130

127131

128-
def default_label_formatter_from_workload_description(
129-
workload_command_summary_map, iteration, experiment_file, workload_id, githash
130-
):
131-
"""Determines the label to be used for plotting from the given data."""
132-
if workload_id not in workload_command_summary_map.keys():
133-
print(
134-
colored(
135-
f"Cannot find workload {workload_id} in {workload_command_summary_map} for {githash}",
136-
"red",
137-
)
138-
)
139-
return
140-
data = json.loads(workload_command_summary_map[workload_id]["workload_description"])
132+
@dataclass
133+
class WorkloadDescription:
134+
"""Workload description extracted from summary file"""
135+
136+
request_type: str
137+
rps: str
138+
payload: str
139+
canisters: str
140+
141141

142+
def workload_description_from_json(data, iteration, workload_command_summary_map, workload_id, experiment_file):
142143
if data[1] is None:
143144
# If the request type isn't set directly via "method" in the toml file, try to set it
144145
# based on whether "-u" has been given
@@ -150,21 +151,34 @@ def default_label_formatter_from_workload_description(
150151
else:
151152
request_type = str(data[1])
152153

153-
label = (
154-
",".join(data[0])
155-
+ " - req type: "
156-
+ request_type
157-
+ " - "
158-
+ str(data[3])
159-
+ " rps"
160-
+ " - iter: "
161-
+ str(iteration)
154+
return WorkloadDescription(
155+
request_type=request_type,
156+
rps=str(data[3]),
157+
payload=str(data[5]),
158+
canisters=",".join(data[0])
162159
)
163-
if data[5] is not None:
164-
payload_tmp = str(data[5])
165-
if len(payload_tmp) > 32:
166-
payload_tmp = payload_tmp[30] + ".."
167-
label = label + " - payload: " + payload_tmp
160+
161+
162+
def default_label_formatter_from_workload_description(
163+
workload_command_summary_map, iteration, experiment_file, workload_id, githash
164+
):
165+
"""Determines the label to be used for plotting from the given data."""
166+
if workload_id not in workload_command_summary_map.keys():
167+
print(
168+
colored(
169+
f"Cannot find workload {workload_id} in {workload_command_summary_map} for {githash}",
170+
"red",
171+
)
172+
)
173+
return
174+
data = json.loads(
175+
workload_command_summary_map[workload_id]["workload_description"])
176+
wd = workload_description_from_json(data, iteration, workload_command_summary_map, workload_id, experiment_file)
177+
178+
label = wd.canisters + " - req type: " + \
179+
wd.request_type + " - " + f"{float(wd.rps):.1f}" + " rps"
180+
if wd.payload is not None:
181+
label = label + " - payload: " + wd.payload
168182

169183
# Attempt to replace the canister ID with canister names
170184
for canister_name, canister_ids in experiment_file.canister_id.items():
@@ -194,21 +208,25 @@ def parse_rps_experiment_with_evaluated_summary(data, githash, timestamp, meta_d
194208
base_dir = os.path.join(FLAGS.experiment_data, githash, timestamp)
195209
assert os.path.exists(base_dir)
196210

197-
experiment_file = report.parse_experiment_file(data)
211+
experiment_file = report.parse_experiment_file(data, strict=False)
198212
xvalue = experiment_file.t_experiment_start
199213

200214
for iteration, workloads in report.find_experiment_summaries(base_dir).items():
201215

202216
for workload_id, summary_files in workloads.items():
203217
# Find xlabel for given iteration
204218
if f_label is None:
205-
label = str(workload_id) + " " + str(experiment_file.xlabels[iteration - 1]) + " rps"
219+
label = str(workload_id) + " " + \
220+
f"{experiment_file.xlabels[iteration - 1]:.1f}" + " rps"
206221
else:
207-
path = os.path.join(base_dir, str(iteration), "workload_command_summary_map.json")
222+
path = os.path.join(base_dir, str(
223+
iteration), "workload_command_summary_map.json")
208224
if os.path.exists(path):
209225
with open(path, "r") as summary_map_f:
210-
workload_command_summary_map = json.loads(summary_map_f.read())
211-
label = f_label(workload_command_summary_map, iteration, experiment_file, workload_id, githash)
226+
workload_command_summary_map = json.loads(
227+
summary_map_f.read())
228+
label = f_label(
229+
workload_command_summary_map, iteration, experiment_file, workload_id, githash)
212230

213231
else:
214232
# No workload summary mapping file, so we cannot look up anything useful as label
@@ -230,7 +248,8 @@ def parse_rps_experiment_with_evaluated_summary(data, githash, timestamp, meta_d
230248
}
231249
)
232250

233-
raw_data[label] = raw_data.get(label, []) + [(xvalue, yvalue, label)]
251+
raw_data[label] = raw_data.get(
252+
label, []) + [(xvalue, yvalue, label)]
234253
added = True
235254

236255
return added
@@ -249,7 +268,8 @@ def parse_rps_experiment_failure_rate(data, githash, timestamp, meta_data, raw_d
249268

250269
def parse_rps_experiment_latency(data, githash, timestamp, meta_data, raw_data):
251270
return parse_rps_experiment_with_evaluated_summary(
252-
data, githash, timestamp, meta_data, raw_data, lambda evaluated_summaries: evaluated_summaries.percentiles[90]
271+
data, githash, timestamp, meta_data, raw_data, lambda evaluated_summaries: evaluated_summaries.percentiles[
272+
90]
253273
)
254274

255275

@@ -261,7 +281,8 @@ def parse_rps_experiment_max_capacity(data, githash, experiment_timestamp, meta_
261281
"""
262282
added = False
263283

264-
base_dir = os.path.join(FLAGS.experiment_data, githash, experiment_timestamp)
284+
base_dir = os.path.join(FLAGS.experiment_data,
285+
githash, experiment_timestamp)
265286
assert os.path.exists(base_dir)
266287

267288
experiment_file = report.parse_experiment_file(data, strict=False)
@@ -271,7 +292,8 @@ def parse_rps_experiment_max_capacity(data, githash, experiment_timestamp, meta_
271292
MAX_FAILURE_RATE = 0.3
272293
MAX_LATENCY = 20000
273294

274-
experiment_details = report.parse_experiment_details_with_fallback_duration(data["experiment_details"])
295+
experiment_details = report.parse_experiment_details_with_fallback_duration(
296+
data["experiment_details"])
275297
experiment_summaries = None
276298
experiment_summaries = report.find_experiment_summaries(base_dir)
277299

@@ -296,7 +318,8 @@ def parse_rps_experiment_max_capacity(data, githash, experiment_timestamp, meta_
296318
)
297319

298320
label = f"workload {idx}"
299-
raw_data[label] = raw_data.get(label, []) + [(xvalue, yvalue, "Maximum capacity")]
321+
raw_data[label] = raw_data.get(
322+
label, []) + [(xvalue, yvalue, "Maximum capacity")]
300323
added = True
301324

302325
return added
@@ -323,10 +346,12 @@ def parse_xnet_experiment(data, githash, timestamp, meta_data, raw_data):
323346
)
324347

325348
print(
326-
" {:40} {:30} {:10.3f}".format(data["experiment_name"], convert_date(data["t_experiment_start"]), yvalue)
349+
" {:40} {:30} {:10.3f}".format(
350+
data["experiment_name"], convert_date(data["t_experiment_start"]), yvalue)
327351
)
328352
label = None
329-
raw_data[label] = raw_data.get(label, []) + [(xvalue, yvalue, "Xnet capacity")]
353+
raw_data[label] = raw_data.get(
354+
label, []) + [(xvalue, yvalue, "Xnet capacity")]
330355
return True
331356

332357
else:
@@ -358,10 +383,12 @@ def parse_statesync_experiment(data, githash, timestamp, meta_data, raw_data):
358383

359384
if yvalue > 0:
360385
print(
361-
" {:40} {:30} {:10.3f}".format(data["experiment_name"], convert_date(data["t_experiment_start"]), yvalue)
386+
" {:40} {:30} {:10.3f}".format(
387+
data["experiment_name"], convert_date(data["t_experiment_start"]), yvalue)
362388
)
363389
label = False
364-
raw_data[label] = raw_data.get(label, []) + [(xvalue, yvalue, "Statesync capacity")]
390+
raw_data[label] = raw_data.get(
391+
label, []) + [(xvalue, yvalue, "Statesync capacity")]
365392
return True
366393
else:
367394
return False
@@ -376,7 +403,8 @@ def parse_mixed_workload_experiment(
376403
def eval_function(evaluated_summaries):
377404
return evaluated_summaries.get_median_failure_rate()
378405

379-
base_dir = os.path.join(FLAGS.experiment_data, githash, experiment_timestamp)
406+
base_dir = os.path.join(FLAGS.experiment_data,
407+
githash, experiment_timestamp)
380408
print(colored(f"Parsing: {base_dir}", "grey", attrs=["bold"]))
381409
assert os.path.exists(base_dir)
382410

@@ -436,8 +464,10 @@ def find_results(
436464
timestamp,
437465
) not in BLACKLIST:
438466

439-
report_file = report.parse_experiment_file(data, strict=False)
440-
results.append(ExperimentResultDirectory(result, report_file, githash, timestamp))
467+
report_file = report.parse_experiment_file(
468+
data, strict=False)
469+
results.append(ExperimentResultDirectory(
470+
result, report_file, githash, timestamp))
441471

442472
except ValueError as e: # Replace with proper exception
443473
print(traceback.format_exc())
@@ -496,7 +526,8 @@ def render_results(
496526
ensure_report_generated(githash, timestamp)
497527

498528
if len(raw_data) < 1:
499-
raise Exception(f"Could not find any data for: {testnets} {experiment_names} {experiment_type}")
529+
raise Exception(
530+
f"Could not find any data for: {testnets} {experiment_names} {experiment_type}")
500531

501532
meta_data = sorted(meta_data, key=lambda x: x["timestamp"])
502533

@@ -564,13 +595,34 @@ def render_results(
564595
}
565596

566597
data["plot_exp1_query"] = render_results(
567-
["experiment_1", "run_system_baseline_experiment", "system-baseline-experiment"],
598+
["experiment_1", "run_system_baseline_experiment",
599+
"system-baseline-experiment"],
568600
["query"],
569601
parse_rps_experiment_max_capacity,
570602
4000,
571603
)
604+
data["plot_exp1_query_failure_rate"] = render_results(
605+
["experiment_1", "run_system_baseline_experiment",
606+
"system-baseline-experiment"],
607+
["query"],
608+
parse_rps_experiment_failure_rate,
609+
None,
610+
yaxis_title="Failure rate",
611+
# time_start=1666142871,
612+
)
613+
data["plot_exp1_query_latency"] = render_results(
614+
["experiment_1", "run_system_baseline_experiment",
615+
"system-baseline-experiment"],
616+
["query"],
617+
parse_rps_experiment_latency,
618+
None,
619+
yaxis_title="Latency",
620+
# time_start=1666142871,
621+
)
622+
572623
data["plot_exp1_update"] = render_results(
573-
["experiment_1", "run_system_baseline_experiment", "system-baseline-experiment"],
624+
["experiment_1", "run_system_baseline_experiment",
625+
"system-baseline-experiment"],
574626
["update"],
575627
parse_rps_experiment_max_capacity,
576628
800,
@@ -592,12 +644,15 @@ def render_results(
592644
yaxis_title="State Sync duration [s]",
593645
)
594646

595-
data["plot_xnet"] = render_results(["run_xnet_experiment"], ["query"], parse_xnet_experiment, 5500)
647+
data["plot_xnet"] = render_results(["run_xnet_experiment"], [
648+
"query"], parse_xnet_experiment, 5500)
596649

597650
render_mixed_workload_experiment(data, "qr", "qr.toml")
598651
render_mixed_workload_experiment(data, "sha256", "sha256.toml")
599-
render_mixed_workload_experiment(data, "http_outcall", "canister-http-benchmark.toml")
600-
render_mixed_workload_experiment(data, "mixed_counter", "mixed-query-update.toml")
652+
render_mixed_workload_experiment(
653+
data, "http_outcall", "canister-http-benchmark.toml")
654+
render_mixed_workload_experiment(
655+
data, "mixed_counter", "mixed-query-update.toml")
601656

602657
# Render the internal CD overview
603658
with open(f"{FLAGS.experiment_data}/cd-overview.html", "w") as outfile:
@@ -621,6 +676,7 @@ def render_results(
621676
print("🎉 Report written")
622677

623678
LOGO = "fully_on_chain-default-bg_dark.svg"
624-
shutil.copy(os.path.join(TEMPLATE_BASEDIR, LOGO), FLAGS.experiment_data)
679+
shutil.copy(os.path.join(TEMPLATE_BASEDIR, LOGO),
680+
FLAGS.experiment_data)
625681
if len(FLAGS.asset_root) > 0:
626682
shutil.copy(os.path.join(TEMPLATE_BASEDIR, LOGO), FLAGS.asset_root)

scalability/setup.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[flake8]
2+
max-line-length = 160

0 commit comments

Comments
 (0)