Skip to content

Commit 2df9086

Browse files
authored
Merge pull request #2 from dbccccccc/test
fix 403!
2 parents 9ee7a71 + 3c184d6 commit 2df9086

File tree

2 files changed

+269
-89
lines changed

2 files changed

+269
-89
lines changed

pressure_test.py

Lines changed: 83 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""
22
Pressure Test for the OpenAI TTS API Server
33
4-
This script sends concurrent requests to the API server to test its performance under load.
4+
This script continuously sends requests to the API server until it encounters a failure.
55
"""
66

77
import asyncio
@@ -112,8 +112,16 @@ async def send_request(session, url, voice, text_length, request_num, save_dir=N
112112
"response_size": 0
113113
}
114114

115-
async def run_pressure_test(num_requests, concurrency, server_url, text_length="medium", save_audio=False):
116-
"""Run the pressure test with the specified parameters."""
115+
async def run_test(server_url, text_length="medium", save_audio=False, num_requests=None, concurrency=1):
116+
"""Run the test with specified parameters.
117+
118+
Args:
119+
server_url: URL of the TTS server
120+
text_length: Length of test text (short, medium, long)
121+
save_audio: Whether to save audio files
122+
num_requests: Number of requests to send (None for continuous until failure)
123+
concurrency: Number of concurrent requests to send
124+
"""
117125

118126
if not server_url.endswith('/v1/audio/speech'):
119127
server_url = f"{server_url.rstrip('/')}/v1/audio/speech"
@@ -123,10 +131,15 @@ async def run_pressure_test(num_requests, concurrency, server_url, text_length="
123131
if save_audio:
124132
save_dir = Path('test_output')
125133
save_dir.mkdir(exist_ok=True)
126-
127-
print(f"Starting pressure test with {num_requests} total requests, {concurrency} concurrent connections")
134+
135+
mode = "fixed" if num_requests else "continuous"
136+
137+
print(f"Starting {mode} test with {concurrency} concurrent requests")
128138
print(f"Server URL: {server_url}")
129139
print(f"Text length: {text_length}")
140+
if num_requests:
141+
print(f"Number of requests: {num_requests}")
142+
print(f"Concurrency level: {concurrency}")
130143
if save_audio:
131144
print(f"Saving audio files to: {save_dir}")
132145
print("-" * 60)
@@ -135,40 +148,62 @@ async def run_pressure_test(num_requests, concurrency, server_url, text_length="
135148
start_time = time.time()
136149

137150
async with aiohttp.ClientSession() as session:
138-
tasks = []
139-
for i in range(num_requests):
140-
# Cycle through different voices
141-
voice = VOICES[i % len(VOICES)]
142-
143-
# Add a small delay between creating tasks to avoid overwhelming the server at startup
144-
await asyncio.sleep(0.05)
151+
if num_requests:
152+
# Fixed number of requests mode
153+
request_nums = list(range(1, num_requests + 1))
145154

146-
task = asyncio.create_task(send_request(session, server_url, voice, text_length, i + 1, save_dir))
147-
tasks.append(task)
155+
# Process requests in batches according to concurrency
156+
for i in range(0, len(request_nums), concurrency):
157+
batch = request_nums[i:i+concurrency]
158+
tasks = []
159+
160+
for req_num in batch:
161+
voice = VOICES[(req_num - 1) % len(VOICES)]
162+
tasks.append(send_request(session, server_url, voice, text_length, req_num, save_dir))
163+
164+
batch_results = await asyncio.gather(*tasks)
165+
results.extend(batch_results)
166+
167+
# Check if any request in the batch failed
168+
if any(not r["success"] for r in batch_results):
169+
print("Stopping test due to request failure")
170+
break
171+
else:
172+
# Continuous mode (until failure)
173+
request_num = 1
174+
failed = False
148175

149-
# If we've reached the concurrency limit, wait for some tasks to complete
150-
if len(tasks) >= concurrency:
151-
done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
152-
results.extend([task.result() for task in done])
153-
tasks = list(pending) # Convert the pending set back to a list
154-
155-
# Wait for any remaining tasks
156-
if tasks:
157-
done, _ = await asyncio.wait(tasks)
158-
results.extend([task.result() for task in done])
176+
while not failed:
177+
tasks = []
178+
179+
for i in range(concurrency):
180+
curr_req_num = request_num + i
181+
voice = VOICES[(curr_req_num - 1) % len(VOICES)]
182+
tasks.append(send_request(session, server_url, voice, text_length, curr_req_num, save_dir))
183+
184+
batch_results = await asyncio.gather(*tasks)
185+
results.extend(batch_results)
186+
187+
# Check if any request in the batch failed
188+
if any(not r["success"] for r in batch_results):
189+
failed = True
190+
print("Stopping test due to request failure")
191+
break
192+
193+
request_num += concurrency
159194

160195
end_time = time.time()
161196
total_duration = end_time - start_time
162197

163198
print("\n" + "=" * 60)
164-
print(f"Pressure Test Results ({text_length} text)")
199+
print(f"Test Results ({text_length} text, {'continuous' if not num_requests else num_requests} requests, {concurrency} concurrency)")
165200
print("=" * 60)
166201

167202
# Calculate and display statistics
168203
successful_reqs = [r for r in results if r["success"]]
169204
failed_reqs = [r for r in results if not r["success"]]
170205

171-
success_rate = len(successful_reqs) / num_requests * 100 if num_requests > 0 else 0
206+
success_rate = len(successful_reqs) / len(results) * 100 if results else 0
172207

173208
# Calculate response time statistics
174209
if successful_reqs:
@@ -183,46 +218,51 @@ async def run_pressure_test(num_requests, concurrency, server_url, text_length="
183218
avg_size = statistics.mean(sizes) / 1024 # KB
184219
total_size = sum(sizes) / (1024 * 1024) # MB
185220

186-
print(f"Success Rate: {success_rate:.1f}% ({len(successful_reqs)}/{num_requests})")
221+
print(f"Total Successful Requests: {len(successful_reqs)}")
222+
print(f"Success Rate: {success_rate:.1f}%")
187223
print(f"Total Test Duration: {total_duration:.2f} seconds")
188224
print(f"Average Response Time: {avg_duration:.3f} seconds")
189225
print(f"Median Response Time: {median_duration:.3f} seconds")
190226
print(f"Min Response Time: {min_duration:.3f} seconds")
191227
print(f"Max Response Time: {max_duration:.3f} seconds")
192228
print(f"Average Response Size: {avg_size:.1f} KB")
193229
print(f"Total Data Transferred: {total_size:.2f} MB")
194-
print(f"Requests per Second: {num_requests / total_duration:.2f}")
230+
print(f"Requests per Second: {len(results) / total_duration:.2f}")
195231
print(f"Throughput: {(total_size * 8) / total_duration:.2f} Mbps")
196232
else:
197-
print(f"Success Rate: 0% (0/{num_requests})")
233+
print(f"Success Rate: 0%")
198234
print(f"Total Test Duration: {total_duration:.2f} seconds")
199235

200-
# Show error breakdown if there are failures
236+
# Show error details for the failures
201237
if failed_reqs:
202-
print("\nError Breakdown:")
203-
error_counts = {}
204-
for req in failed_reqs:
205-
error = req.get("error", f"HTTP {req['status']}")
206-
error_counts[error] = error_counts.get(error, 0) + 1
238+
print("\nFailure Details:")
239+
for i, failed_req in enumerate(failed_reqs[:5]): # Show up to 5 failures
240+
error = failed_req.get("error", f"HTTP {failed_req['status']}")
241+
print(f" Request Number: {failed_req['request_num']}")
242+
print(f" Voice: {failed_req['voice']}")
243+
print(f" Error: {error}")
244+
print(f" Duration: {failed_req['duration']:.2f} seconds")
245+
if i < len(failed_reqs) - 1 and i < 4: # Add separator except after the last one
246+
print(" ---")
207247

208-
for error, count in error_counts.items():
209-
print(f" {error}: {count} occurrences")
248+
if len(failed_reqs) > 5:
249+
print(f" ... and {len(failed_reqs) - 5} more failures")
210250

211251
if __name__ == "__main__":
212252
parser = argparse.ArgumentParser(description="Pressure test for OpenAI TTS API Server")
213-
parser.add_argument("-n", "--num-requests", type=int, default=10, help="Total number of requests to send")
214-
parser.add_argument("-c", "--concurrency", type=int, default=2, help="Number of concurrent connections")
215253
parser.add_argument("-u", "--url", type=str, default="http://localhost:7000", help="Server URL")
216254
parser.add_argument("-t", "--text-length", type=str, choices=["short", "medium", "long"], default="medium",
217255
help="Length of text to use for testing")
218256
parser.add_argument("-s", "--save-audio", action="store_true", help="Save audio files to test_output directory")
257+
parser.add_argument("-n", "--num-requests", type=int, help="Number of requests to send (default: continuous until failure)")
258+
parser.add_argument("-c", "--concurrency", type=int, default=1, help="Number of concurrent requests (default: 1)")
219259

220260
args = parser.parse_args()
221261

222-
asyncio.run(run_pressure_test(
223-
args.num_requests,
224-
args.concurrency,
262+
asyncio.run(run_test(
225263
args.url,
226264
args.text_length,
227-
args.save_audio
265+
args.save_audio,
266+
args.num_requests,
267+
args.concurrency
228268
))

0 commit comments

Comments
 (0)