8
8
9
9
from redis_benchmarks_specification .__common__ .runner import get_benchmark_specs
10
10
11
+
12
+
11
13
# logging settings
12
14
logging .basicConfig (
13
15
format = "%(asctime)s %(levelname)-4s %(message)s" ,
16
18
)
17
19
18
20
21
+ def clean_number (value ):
22
+ """ Cleans and converts numeric values from CSV, handling B (billion), M (million), K (thousand). """
23
+ try :
24
+ value = value .replace ("," , "" ).strip () # Remove commas and spaces
25
+
26
+ # Determine the scale factor
27
+ multiplier = 1
28
+ if value .endswith ("B" ):
29
+ multiplier = 1_000_000_000 # Billion
30
+ value = value [:- 1 ] # Remove "B"
31
+ elif value .endswith ("M" ):
32
+ multiplier = 1_000_000 # Million
33
+ value = value [:- 1 ] # Remove "M"
34
+ elif value .endswith ("K" ):
35
+ multiplier = 1_000 # Thousand
36
+ value = value [:- 1 ] # Remove "K"
37
+
38
+ return int (float (value ) * multiplier ) # Convert to full number
39
+ except ValueError :
40
+ logging .error (f"Skipping invalid count value: { value } " )
41
+ return 0 # Default to 0 if invalid
42
+
43
+ def get_arg_value (args , flag , default ):
44
+ """Extract integer values safely from CLI arguments"""
45
+ if flag in args :
46
+ try :
47
+ val = (
48
+ args [args .index (flag ) + 1 ].lstrip ("=" ).strip ()
49
+ ) # Remove any leading '='
50
+ return int (val ) # Convert to integer safely
51
+ except (IndexError , ValueError ):
52
+ logging .error (f"Failed to extract { flag } , using default: { default } " )
53
+ return default # Return default if not found or invalid
54
+
55
+
19
56
def generate_stats_cli_command_logic (args , project_name , project_version ):
20
57
logging .info (
21
58
"Using: {project_name} {project_version}" .format (
@@ -55,10 +92,14 @@ def generate_stats_cli_command_logic(args, project_name, project_version):
55
92
)
56
93
priority_json = json .load (fd )
57
94
tracked_groups = []
95
+ tracked_groups_hist = {}
58
96
override_enabled = args .override_tests
59
97
fail_on_required_diff = args .fail_on_required_diff
60
98
overall_result = True
61
99
test_names = []
100
+ pipelines = {}
101
+ connections = {}
102
+ data_sizes = {}
62
103
defaults_filename = args .defaults_filename
63
104
64
105
for test_file in testsuite_spec_files :
@@ -83,6 +124,13 @@ def generate_stats_cli_command_logic(args, project_name, project_version):
83
124
test_names .append (test_name )
84
125
group = ""
85
126
is_memtier = False
127
+
128
+ ## defaults
129
+ pipeline_size = 1
130
+ clients = 50
131
+ threads = 4
132
+ data_size = 32
133
+
86
134
if "memtier" in test_name :
87
135
is_memtier = True
88
136
tested_groups = []
@@ -101,6 +149,32 @@ def generate_stats_cli_command_logic(args, project_name, project_version):
101
149
tested_commands .append (tested_command .lower ())
102
150
if is_memtier :
103
151
arguments = benchmark_config ["clientconfig" ]["arguments" ]
152
+ arg_list = (
153
+ benchmark_config ["clientconfig" ]["arguments" ]
154
+ .replace ('"' , "" )
155
+ .split ()
156
+ )
157
+
158
+ data_size = get_arg_value (arg_list , "--data-size" , data_size )
159
+ data_size = get_arg_value (arg_list , "-d" , data_size )
160
+
161
+ # Extract values using the safer parsing function
162
+ pipeline_size = get_arg_value (arg_list , "--pipeline" , pipeline_size )
163
+ pipeline_size = get_arg_value (
164
+ arg_list , "-P" , pipeline_size
165
+ ) # Support short form
166
+
167
+ # Extract values using the safer parsing function
168
+ clients = get_arg_value (arg_list , "--clients" , clients )
169
+ clients = get_arg_value (
170
+ arg_list , "-c" , clients
171
+ ) # Support short form
172
+
173
+ threads = get_arg_value (arg_list , "--threads" , threads )
174
+ threads = get_arg_value (
175
+ arg_list , "-t" , threads
176
+ ) # Support short form
177
+
104
178
arguments_split = arguments .split ("--command" )
105
179
106
180
if len (arguments_split ) == 1 :
@@ -133,9 +207,27 @@ def generate_stats_cli_command_logic(args, project_name, project_version):
133
207
134
208
group = command_json ["group" ]
135
209
if group not in tested_groups :
210
+
136
211
tested_groups .append (group )
137
212
if group not in tracked_groups :
138
213
tracked_groups .append (group )
214
+ tracked_groups_hist [group ]= 0
215
+ tracked_groups_hist [group ]= tracked_groups_hist [group ]+ 1
216
+
217
+ # Calculate total connections
218
+ total_connections = clients * threads
219
+
220
+ if pipeline_size not in pipelines :
221
+ pipelines [pipeline_size ] = 0
222
+ pipelines [pipeline_size ] = pipelines [pipeline_size ] + 1
223
+
224
+ if total_connections not in connections :
225
+ connections [total_connections ] = 0
226
+ connections [total_connections ] = connections [total_connections ] + 1
227
+
228
+ if data_size not in data_sizes :
229
+ data_sizes [data_size ] = 0
230
+ data_sizes [data_size ] = data_sizes [data_size ] + 1
139
231
140
232
if tested_commands != origin_tested_commands :
141
233
requires_override = True
@@ -281,10 +373,10 @@ def generate_stats_cli_command_logic(args, project_name, project_version):
281
373
if "cmdstat_" not in cmdstat :
282
374
continue
283
375
cmdstat = cmdstat .replace ("cmdstat_" , "" )
284
- count = int (row [1 ])
376
+ count = clean_number (row [1 ])
285
377
usecs = None
286
378
if len (row ) > 2 :
287
- usecs = int (row [2 ])
379
+ usecs = clean_number (row [2 ])
288
380
total_usecs += usecs
289
381
if count == 0 :
290
382
continue
@@ -470,11 +562,11 @@ def generate_stats_cli_command_logic(args, project_name, project_version):
470
562
logging .info ("Top 10 fully tracked?: {}" .format (len (top_10_missing ) == 0 ))
471
563
logging .info ("Top 30 fully tracked?: {}" .format (len (top_30_missing ) == 0 ))
472
564
if len (top_30_missing ) > 0 :
473
- logging .info ("\t \t Total missing for Top 30: {}" . format ( len (top_30_missing )) )
565
+ logging .info (f "\t \t Total missing for Top 30: { len (top_30_missing )} . { top_30_missing } " )
474
566
475
567
logging .info ("Top 50 fully tracked?: {}" .format (len (top_50_missing ) == 0 ))
476
568
if len (top_50_missing ) > 0 :
477
- logging .info ("\t \t Total missing for Top 50: {}" . format ( len (top_50_missing )) )
569
+ logging .info (f "\t \t Total missing for Top 50: { len (top_50_missing )} . { top_50_missing } " )
478
570
479
571
if overall_result is False and fail_on_required_diff :
480
572
logging .error (
@@ -500,3 +592,71 @@ def generate_stats_cli_command_logic(args, project_name, project_version):
500
592
conn .sadd (tested_groups_key , group )
501
593
for command in list (tracked_commands_json .keys ()):
502
594
conn .sadd (tested_commands_key , command )
595
+
596
+ logging .info (f"There is a total of : { len (tracked_groups )} tracked command groups." )
597
+ logging .info (
598
+ f"There is a total of : { len (list (tracked_commands_json .keys ()))} tracked commands."
599
+ )
600
+ # Save pipeline count to CSV
601
+ csv_filename = "memtier_pipeline_count.csv"
602
+ with open (csv_filename , "w" , newline = "" ) as csvfile :
603
+ fieldnames = ["pipeline" , "count" ]
604
+ writer = csv .DictWriter (csvfile , fieldnames = fieldnames )
605
+ writer .writeheader ()
606
+ for pipeline_size in sorted (pipelines .keys ()):
607
+ writer .writerow (
608
+ {"pipeline" : pipeline_size , "count" : pipelines [pipeline_size ]}
609
+ )
610
+
611
+ logging .info (f"Pipeline count data saved to { csv_filename } " )
612
+
613
+ csv_filename = "memtier_connection_count.csv"
614
+ with open (csv_filename , "w" , newline = "" ) as csvfile :
615
+ fieldnames = ["connections" , "count" ]
616
+ writer = csv .DictWriter (csvfile , fieldnames = fieldnames )
617
+ writer .writeheader ()
618
+
619
+ # Sort connections dictionary by keys before writing
620
+ for connection_count in sorted (connections .keys ()):
621
+ writer .writerow (
622
+ {
623
+ "connections" : connection_count ,
624
+ "count" : connections [connection_count ],
625
+ }
626
+ )
627
+
628
+ logging .info (f"Sorted connection count data saved to { csv_filename } " )
629
+
630
+ csv_filename = "memtier_data_size_histogram.csv"
631
+ with open (csv_filename , "w" , newline = "" ) as csvfile :
632
+ fieldnames = ["data_size" , "count" ]
633
+ writer = csv .DictWriter (csvfile , fieldnames = fieldnames )
634
+ writer .writeheader ()
635
+
636
+ # Sort connections dictionary by keys before writing
637
+ for data_size in sorted (data_sizes .keys ()):
638
+ writer .writerow (
639
+ {
640
+ "data_size" : data_size ,
641
+ "count" : data_sizes [data_size ],
642
+ }
643
+ )
644
+
645
+ logging .info (f"Sorted data size count data saved to { csv_filename } " )
646
+
647
+ csv_filename = "memtier_groups_histogram.csv"
648
+ with open (csv_filename , "w" , newline = "" ) as csvfile :
649
+ fieldnames = ["group" , "count" ]
650
+ writer = csv .DictWriter (csvfile , fieldnames = fieldnames )
651
+ writer .writeheader ()
652
+
653
+ # Sort connections dictionary by keys before writing
654
+ for group in sorted (tracked_groups_hist .keys ()):
655
+ writer .writerow (
656
+ {
657
+ "group" : group ,
658
+ "count" : tracked_groups_hist [group ],
659
+ }
660
+ )
661
+
662
+ logging .info (f"Sorted command groups count data saved to { csv_filename } " )
0 commit comments