22
22
23
23
FLAGS = gflags .FLAGS
24
24
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" )
27
29
gflags .DEFINE_boolean ("regenerate" , False , "Regenerate all reports" )
28
30
29
31
TEMPLATE_BASEDIR = "templates"
51
53
("c610c3fec6ea8acd1b831099317cc0b98fe4b310" , "1649613136" ),
52
54
("b0d3c45e14b116f8213ed88dea064fbc631c038c" , "1667834847" ),
53
55
("903c8b3a520c69a953b4cdf6468bf2612e86be49" , "1660642902" ),
56
+ ("2a0ff6c34e61d64e6fe8b0ce47e7edbec30e8c1e" , "1674507377" ),
54
57
]
55
58
56
59
@@ -112,7 +115,8 @@ def copy_results(git_revision: str, timestamp: str):
112
115
"""Copy results for an individual experiment to the asset canister."""
113
116
if len (FLAGS .asset_root ) > 0 :
114
117
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 )
116
120
target_dir = os .path .join (FLAGS .asset_root , git_revision , timestamp )
117
121
118
122
# Search for svg files in the iteration folders
@@ -125,20 +129,17 @@ def copy_results(git_revision: str, timestamp: str):
125
129
shutil .copy (svg , svg_target_dir )
126
130
127
131
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
+
141
141
142
+ def workload_description_from_json (data , iteration , workload_command_summary_map , workload_id , experiment_file ):
142
143
if data [1 ] is None :
143
144
# If the request type isn't set directly via "method" in the toml file, try to set it
144
145
# based on whether "-u" has been given
@@ -150,21 +151,34 @@ def default_label_formatter_from_workload_description(
150
151
else :
151
152
request_type = str (data [1 ])
152
153
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 ])
162
159
)
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
168
182
169
183
# Attempt to replace the canister ID with canister names
170
184
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
194
208
base_dir = os .path .join (FLAGS .experiment_data , githash , timestamp )
195
209
assert os .path .exists (base_dir )
196
210
197
- experiment_file = report .parse_experiment_file (data )
211
+ experiment_file = report .parse_experiment_file (data , strict = False )
198
212
xvalue = experiment_file .t_experiment_start
199
213
200
214
for iteration , workloads in report .find_experiment_summaries (base_dir ).items ():
201
215
202
216
for workload_id , summary_files in workloads .items ():
203
217
# Find xlabel for given iteration
204
218
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"
206
221
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" )
208
224
if os .path .exists (path ):
209
225
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 )
212
230
213
231
else :
214
232
# 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
230
248
}
231
249
)
232
250
233
- raw_data [label ] = raw_data .get (label , []) + [(xvalue , yvalue , label )]
251
+ raw_data [label ] = raw_data .get (
252
+ label , []) + [(xvalue , yvalue , label )]
234
253
added = True
235
254
236
255
return added
@@ -249,7 +268,8 @@ def parse_rps_experiment_failure_rate(data, githash, timestamp, meta_data, raw_d
249
268
250
269
def parse_rps_experiment_latency (data , githash , timestamp , meta_data , raw_data ):
251
270
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 ]
253
273
)
254
274
255
275
@@ -261,7 +281,8 @@ def parse_rps_experiment_max_capacity(data, githash, experiment_timestamp, meta_
261
281
"""
262
282
added = False
263
283
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 )
265
286
assert os .path .exists (base_dir )
266
287
267
288
experiment_file = report .parse_experiment_file (data , strict = False )
@@ -271,7 +292,8 @@ def parse_rps_experiment_max_capacity(data, githash, experiment_timestamp, meta_
271
292
MAX_FAILURE_RATE = 0.3
272
293
MAX_LATENCY = 20000
273
294
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" ])
275
297
experiment_summaries = None
276
298
experiment_summaries = report .find_experiment_summaries (base_dir )
277
299
@@ -296,7 +318,8 @@ def parse_rps_experiment_max_capacity(data, githash, experiment_timestamp, meta_
296
318
)
297
319
298
320
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" )]
300
323
added = True
301
324
302
325
return added
@@ -323,10 +346,12 @@ def parse_xnet_experiment(data, githash, timestamp, meta_data, raw_data):
323
346
)
324
347
325
348
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 )
327
351
)
328
352
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" )]
330
355
return True
331
356
332
357
else :
@@ -358,10 +383,12 @@ def parse_statesync_experiment(data, githash, timestamp, meta_data, raw_data):
358
383
359
384
if yvalue > 0 :
360
385
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 )
362
388
)
363
389
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" )]
365
392
return True
366
393
else :
367
394
return False
@@ -376,7 +403,8 @@ def parse_mixed_workload_experiment(
376
403
def eval_function (evaluated_summaries ):
377
404
return evaluated_summaries .get_median_failure_rate ()
378
405
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 )
380
408
print (colored (f"Parsing: { base_dir } " , "grey" , attrs = ["bold" ]))
381
409
assert os .path .exists (base_dir )
382
410
@@ -436,8 +464,10 @@ def find_results(
436
464
timestamp ,
437
465
) not in BLACKLIST :
438
466
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 ))
441
471
442
472
except ValueError as e : # Replace with proper exception
443
473
print (traceback .format_exc ())
@@ -496,7 +526,8 @@ def render_results(
496
526
ensure_report_generated (githash , timestamp )
497
527
498
528
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 } " )
500
531
501
532
meta_data = sorted (meta_data , key = lambda x : x ["timestamp" ])
502
533
@@ -564,13 +595,34 @@ def render_results(
564
595
}
565
596
566
597
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" ],
568
600
["query" ],
569
601
parse_rps_experiment_max_capacity ,
570
602
4000 ,
571
603
)
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
+
572
623
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" ],
574
626
["update" ],
575
627
parse_rps_experiment_max_capacity ,
576
628
800 ,
@@ -592,12 +644,15 @@ def render_results(
592
644
yaxis_title = "State Sync duration [s]" ,
593
645
)
594
646
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 )
596
649
597
650
render_mixed_workload_experiment (data , "qr" , "qr.toml" )
598
651
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" )
601
656
602
657
# Render the internal CD overview
603
658
with open (f"{ FLAGS .experiment_data } /cd-overview.html" , "w" ) as outfile :
@@ -621,6 +676,7 @@ def render_results(
621
676
print ("🎉 Report written" )
622
677
623
678
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 )
625
681
if len (FLAGS .asset_root ) > 0 :
626
682
shutil .copy (os .path .join (TEMPLATE_BASEDIR , LOGO ), FLAGS .asset_root )
0 commit comments