88
99from redis_benchmarks_specification .__common__ .runner import get_benchmark_specs
1010
11+
12+
1113# logging settings
1214logging .basicConfig (
1315 format = "%(asctime)s %(levelname)-4s %(message)s" ,
1618)
1719
1820
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+
1956def generate_stats_cli_command_logic (args , project_name , project_version ):
2057 logging .info (
2158 "Using: {project_name} {project_version}" .format (
@@ -55,10 +92,14 @@ def generate_stats_cli_command_logic(args, project_name, project_version):
5592 )
5693 priority_json = json .load (fd )
5794 tracked_groups = []
95+ tracked_groups_hist = {}
5896 override_enabled = args .override_tests
5997 fail_on_required_diff = args .fail_on_required_diff
6098 overall_result = True
6199 test_names = []
100+ pipelines = {}
101+ connections = {}
102+ data_sizes = {}
62103 defaults_filename = args .defaults_filename
63104
64105 for test_file in testsuite_spec_files :
@@ -83,6 +124,13 @@ def generate_stats_cli_command_logic(args, project_name, project_version):
83124 test_names .append (test_name )
84125 group = ""
85126 is_memtier = False
127+
128+ ## defaults
129+ pipeline_size = 1
130+ clients = 50
131+ threads = 4
132+ data_size = 32
133+
86134 if "memtier" in test_name :
87135 is_memtier = True
88136 tested_groups = []
@@ -101,6 +149,32 @@ def generate_stats_cli_command_logic(args, project_name, project_version):
101149 tested_commands .append (tested_command .lower ())
102150 if is_memtier :
103151 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+
104178 arguments_split = arguments .split ("--command" )
105179
106180 if len (arguments_split ) == 1 :
@@ -133,9 +207,27 @@ def generate_stats_cli_command_logic(args, project_name, project_version):
133207
134208 group = command_json ["group" ]
135209 if group not in tested_groups :
210+
136211 tested_groups .append (group )
137212 if group not in tracked_groups :
138213 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
139231
140232 if tested_commands != origin_tested_commands :
141233 requires_override = True
@@ -281,10 +373,10 @@ def generate_stats_cli_command_logic(args, project_name, project_version):
281373 if "cmdstat_" not in cmdstat :
282374 continue
283375 cmdstat = cmdstat .replace ("cmdstat_" , "" )
284- count = int (row [1 ])
376+ count = clean_number (row [1 ])
285377 usecs = None
286378 if len (row ) > 2 :
287- usecs = int (row [2 ])
379+ usecs = clean_number (row [2 ])
288380 total_usecs += usecs
289381 if count == 0 :
290382 continue
@@ -470,11 +562,11 @@ def generate_stats_cli_command_logic(args, project_name, project_version):
470562 logging .info ("Top 10 fully tracked?: {}" .format (len (top_10_missing ) == 0 ))
471563 logging .info ("Top 30 fully tracked?: {}" .format (len (top_30_missing ) == 0 ))
472564 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 } " )
474566
475567 logging .info ("Top 50 fully tracked?: {}" .format (len (top_50_missing ) == 0 ))
476568 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 } " )
478570
479571 if overall_result is False and fail_on_required_diff :
480572 logging .error (
@@ -500,3 +592,71 @@ def generate_stats_cli_command_logic(args, project_name, project_version):
500592 conn .sadd (tested_groups_key , group )
501593 for command in list (tracked_commands_json .keys ()):
502594 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