88
99from redis_benchmarks_specification .__common__ .runner import get_benchmark_specs
1010
11+
1112# logging settings
1213logging .basicConfig (
1314 format = "%(asctime)s %(levelname)-4s %(message)s" ,
1617)
1718
1819
20+ def clean_number (value ):
21+ """Cleans and converts numeric values from CSV, handling B (billion), M (million), K (thousand)."""
22+ try :
23+ value = value .replace ("," , "" ).strip () # Remove commas and spaces
24+
25+ # Determine the scale factor
26+ multiplier = 1
27+ if value .endswith ("B" ):
28+ multiplier = 1_000_000_000 # Billion
29+ value = value [:- 1 ] # Remove "B"
30+ elif value .endswith ("M" ):
31+ multiplier = 1_000_000 # Million
32+ value = value [:- 1 ] # Remove "M"
33+ elif value .endswith ("K" ):
34+ multiplier = 1_000 # Thousand
35+ value = value [:- 1 ] # Remove "K"
36+
37+ return int (float (value ) * multiplier ) # Convert to full number
38+ except ValueError :
39+ logging .error (f"Skipping invalid count value: { value } " )
40+ return 0 # Default to 0 if invalid
41+
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,15 @@ 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 (
566+ f"\t \t Total missing for Top 30: { len (top_30_missing )} . { top_30_missing } "
567+ )
474568
475569 logging .info ("Top 50 fully tracked?: {}" .format (len (top_50_missing ) == 0 ))
476570 if len (top_50_missing ) > 0 :
477- logging .info ("\t \t Total missing for Top 50: {}" .format (len (top_50_missing )))
571+ logging .info (
572+ f"\t \t Total missing for Top 50: { len (top_50_missing )} . { top_50_missing } "
573+ )
478574
479575 if overall_result is False and fail_on_required_diff :
480576 logging .error (
@@ -500,3 +596,71 @@ def generate_stats_cli_command_logic(args, project_name, project_version):
500596 conn .sadd (tested_groups_key , group )
501597 for command in list (tracked_commands_json .keys ()):
502598 conn .sadd (tested_commands_key , command )
599+
600+ logging .info (f"There is a total of : { len (tracked_groups )} tracked command groups." )
601+ logging .info (
602+ f"There is a total of : { len (list (tracked_commands_json .keys ()))} tracked commands."
603+ )
604+ # Save pipeline count to CSV
605+ csv_filename = "memtier_pipeline_count.csv"
606+ with open (csv_filename , "w" , newline = "" ) as csvfile :
607+ fieldnames = ["pipeline" , "count" ]
608+ writer = csv .DictWriter (csvfile , fieldnames = fieldnames )
609+ writer .writeheader ()
610+ for pipeline_size in sorted (pipelines .keys ()):
611+ writer .writerow (
612+ {"pipeline" : pipeline_size , "count" : pipelines [pipeline_size ]}
613+ )
614+
615+ logging .info (f"Pipeline count data saved to { csv_filename } " )
616+
617+ csv_filename = "memtier_connection_count.csv"
618+ with open (csv_filename , "w" , newline = "" ) as csvfile :
619+ fieldnames = ["connections" , "count" ]
620+ writer = csv .DictWriter (csvfile , fieldnames = fieldnames )
621+ writer .writeheader ()
622+
623+ # Sort connections dictionary by keys before writing
624+ for connection_count in sorted (connections .keys ()):
625+ writer .writerow (
626+ {
627+ "connections" : connection_count ,
628+ "count" : connections [connection_count ],
629+ }
630+ )
631+
632+ logging .info (f"Sorted connection count data saved to { csv_filename } " )
633+
634+ csv_filename = "memtier_data_size_histogram.csv"
635+ with open (csv_filename , "w" , newline = "" ) as csvfile :
636+ fieldnames = ["data_size" , "count" ]
637+ writer = csv .DictWriter (csvfile , fieldnames = fieldnames )
638+ writer .writeheader ()
639+
640+ # Sort connections dictionary by keys before writing
641+ for data_size in sorted (data_sizes .keys ()):
642+ writer .writerow (
643+ {
644+ "data_size" : data_size ,
645+ "count" : data_sizes [data_size ],
646+ }
647+ )
648+
649+ logging .info (f"Sorted data size count data saved to { csv_filename } " )
650+
651+ csv_filename = "memtier_groups_histogram.csv"
652+ with open (csv_filename , "w" , newline = "" ) as csvfile :
653+ fieldnames = ["group" , "count" ]
654+ writer = csv .DictWriter (csvfile , fieldnames = fieldnames )
655+ writer .writeheader ()
656+
657+ # Sort connections dictionary by keys before writing
658+ for group in sorted (tracked_groups_hist .keys ()):
659+ writer .writerow (
660+ {
661+ "group" : group ,
662+ "count" : tracked_groups_hist [group ],
663+ }
664+ )
665+
666+ logging .info (f"Sorted command groups count data saved to { csv_filename } " )
0 commit comments