7
7
import ruamel .yaml
8
8
from ruamel .yaml .scalarstring import DoubleQuotedScalarString
9
9
10
+
10
11
def calculate_rate_limit (p50_value ):
11
12
if p50_value < 1000 :
12
13
return 100
@@ -15,23 +16,26 @@ def calculate_rate_limit(p50_value):
15
16
else :
16
17
return 10000
17
18
18
- def create_new_test_config (original_config_path , new_config_path , test_name , new_test_name , p50_value ):
19
+
20
+ def create_new_test_config (
21
+ original_config_path , new_config_path , test_name , new_test_name , p50_value
22
+ ):
19
23
# Check if the original configuration file exists
20
24
if not os .path .exists (original_config_path ):
21
25
return False # Indicate failure
22
26
23
27
# Load the original test configuration with ruamel.yaml
24
28
yaml = ruamel .yaml .YAML ()
25
29
yaml .preserve_quotes = True # Preserve quotes in scalar values
26
- with open (original_config_path , 'r' ) as file :
30
+ with open (original_config_path , "r" ) as file :
27
31
config = yaml .load (file )
28
32
29
33
# Calculate the total desired rate limit
30
34
total_rate_limit = calculate_rate_limit (p50_value )
31
35
32
36
# Calculate per-connection rate limit
33
37
# Extract the original arguments
34
- original_arguments = config [' clientconfig' ][ ' arguments' ]
38
+ original_arguments = config [" clientconfig" ][ " arguments" ]
35
39
36
40
# Convert to string if necessary
37
41
if not isinstance (original_arguments , str ):
@@ -46,11 +50,15 @@ def create_new_test_config(original_config_path, new_config_path, test_name, new
46
50
clients_per_thread = 50 # Default value
47
51
threads = 4 # Default value
48
52
49
- clients_match = re .search (r'(?:-c|--clients)(?:[=\s]+)(\d+)' , original_arguments_str )
53
+ clients_match = re .search (
54
+ r"(?:-c|--clients)(?:[=\s]+)(\d+)" , original_arguments_str
55
+ )
50
56
if clients_match :
51
57
clients_per_thread = int (clients_match .group (1 ))
52
58
53
- threads_match = re .search (r'(?:-t|--threads)(?:[=\s]+)(\d+)' , original_arguments_str )
59
+ threads_match = re .search (
60
+ r"(?:-t|--threads)(?:[=\s]+)(\d+)" , original_arguments_str
61
+ )
54
62
if threads_match :
55
63
threads = int (threads_match .group (1 ))
56
64
@@ -61,28 +69,35 @@ def create_new_test_config(original_config_path, new_config_path, test_name, new
61
69
per_connection_rate_limit = max (1 , int (total_rate_limit / total_connections ))
62
70
63
71
# Remove existing rate limit arguments using regex
64
- new_arguments = re .sub (r'--rate(?:-limit(?:ing)?)?(?:\s+\S+)?' , '' , original_arguments_str )
72
+ new_arguments = re .sub (
73
+ r"--rate(?:-limit(?:ing)?)?(?:\s+\S+)?" , "" , original_arguments_str
74
+ )
65
75
66
76
# Append the new '--rate-limiting' argument and its value
67
- new_arguments = f'{ new_arguments .strip ()} --rate-limiting { per_connection_rate_limit } '
77
+ new_arguments = (
78
+ f"{ new_arguments .strip ()} --rate-limiting { per_connection_rate_limit } "
79
+ )
68
80
69
81
# Update the test name to reflect the new test
70
- config [' name' ] = new_test_name
71
- config [' description' ] += f" Rate limited to { total_rate_limit } ops/sec."
82
+ config [" name" ] = new_test_name
83
+ config [" description" ] += f" Rate limited to { total_rate_limit } ops/sec."
72
84
73
85
# Update the arguments in the config
74
- config [' clientconfig' ][ ' arguments' ] = DoubleQuotedScalarString (new_arguments )
86
+ config [" clientconfig" ][ " arguments" ] = DoubleQuotedScalarString (new_arguments )
75
87
76
88
# Ensure the destination directory exists
77
89
os .makedirs (os .path .dirname (new_config_path ), exist_ok = True )
78
90
79
91
# Save the new test configuration
80
- with open (new_config_path , 'w' ) as file :
92
+ with open (new_config_path , "w" ) as file :
81
93
yaml .dump (config , file )
82
94
83
- print (f"Created new test configuration for '{ test_name } ' with total rate limit { total_rate_limit } ops/sec and per-connection rate limit { per_connection_rate_limit } ops/sec." )
95
+ print (
96
+ f"Created new test configuration for '{ test_name } ' with total rate limit { total_rate_limit } ops/sec and per-connection rate limit { per_connection_rate_limit } ops/sec."
97
+ )
84
98
return True # Indicate success
85
99
100
+
86
101
def main ():
87
102
parser = argparse .ArgumentParser (
88
103
description = "Create latency benchmarks" ,
@@ -141,40 +156,47 @@ def main():
141
156
# Execute the TS.REVRANGE command
142
157
# "-" and "+" denote the minimal and maximal timestamps
143
158
result = rts .execute_command ("TS.REVRANGE" , ts_key , "-" , "+" )
144
-
159
+
145
160
# Check if result is not empty
146
161
if result :
147
162
# Extract values and convert to floats
148
163
values = [float (value ) for timestamp , value in result ]
149
164
# Compute the median (p50)
150
165
p50_value = np .median (values )
151
-
166
+
152
167
# Output the results
153
168
print (f"Results for test case '{ test_name } ': p50 rate = { p50_value } " )
154
169
rate = calculate_rate_limit (p50_value )
155
170
156
- original_config_path = f'../redis_benchmarks_specification/test-suites/{ test_name } .yml' # Original test config file
157
- new_test_name = f'latency-rate-limited-{ rate } _qps-{ test_name } '
158
- new_config_path = f'../redis_benchmarks_specification/test-suites/{ new_test_name } .yaml' # New test config file
159
- success = create_new_test_config (original_config_path , new_config_path , test_name , new_test_name , p50_value )
171
+ original_config_path = f"../redis_benchmarks_specification/test-suites/{ test_name } .yml" # Original test config file
172
+ new_test_name = f"latency-rate-limited-{ rate } _qps-{ test_name } "
173
+ new_config_path = f"../redis_benchmarks_specification/test-suites/{ new_test_name } .yaml" # New test config file
174
+ success = create_new_test_config (
175
+ original_config_path ,
176
+ new_config_path ,
177
+ test_name ,
178
+ new_test_name ,
179
+ p50_value ,
180
+ )
160
181
if not success :
161
182
failed_files .append (test_name )
162
183
else :
163
184
print (f"No data available for test case '{ test_name } '." )
164
185
failed_files .append (test_name )
165
-
186
+
166
187
except redis .exceptions .ResponseError as e :
167
188
print (f"Error retrieving data for test case '{ test_name } ': { e } " )
168
189
failed_files .append (test_name )
169
190
except Exception as e :
170
191
print (f"An error occurred while processing test case '{ test_name } ': { e } " )
171
192
failed_files .append (test_name )
172
-
193
+
173
194
# At the end, print out the list of failed files if any
174
195
if failed_files :
175
196
print ("\n The following test cases had missing configuration files or errors:" )
176
197
for test_name in failed_files :
177
198
print (f"- { test_name } " )
178
199
200
+
179
201
if __name__ == "__main__" :
180
202
main ()
0 commit comments