@@ -5,63 +5,31 @@ use std::sync::Arc;
55use std:: time:: Duration ;
66use tokio:: sync:: RwLock ;
77use tokio:: runtime:: Runtime ;
8- use std:: sync:: OnceLock ;
98
10- static BENCHMARK_SERVER : OnceLock < ( u16 , Arc < RwLock < ServerState > > ) > = OnceLock :: new ( ) ;
11-
12- /// Setup shared test server for all benchmarks to reduce overhead
13- async fn setup_shared_benchmark_server ( ) -> Result < ( tokio:: task:: JoinHandle < ( ) > , u16 ) , Box < dyn std:: error:: Error + Send + Sync > > {
9+ /// Setup test server for benchmarking
10+ async fn setup_benchmark_server ( ) -> Result < ( tokio:: task:: JoinHandle < ( ) > , u16 ) , Box < dyn std:: error:: Error + Send + Sync > > {
1411 // Use a fixed port for benchmarks to avoid conflicts
1512 let port = 9001 ;
1613
17- // Load configuration with mock settings for faster startup
18- let mut config = Config :: load ( ) . map_err ( |e| format ! ( "Failed to load config: {e}" ) ) ?;
19- // Override with localhost for faster responses (avoiding external network calls)
20- config. rpc_url = "http://localhost:8899" . to_string ( ) ; // Mock local RPC for benchmarks
21- config. timeouts . http_request_seconds = 1 ; // Reduce timeouts for benchmarks
14+ // Load configuration
15+ let config = Config :: load ( ) . map_err ( |e| format ! ( "Failed to load config: {e}" ) ) ?;
2216
2317 // Create server state
2418 let server_state = ServerState :: new ( config) ;
2519 let state = Arc :: new ( RwLock :: new ( server_state) ) ;
2620
2721 // Start HTTP server with MCP API
28- let handle = start_mcp_server_task ( port, state. clone ( ) ) ;
29-
30- // Store shared server state
31- BENCHMARK_SERVER . set ( ( port, state) ) . ok ( ) ;
22+ let handle = start_mcp_server_task ( port, state) ;
3223
3324 // Give server time to start
34- tokio:: time:: sleep ( Duration :: from_millis ( 100 ) ) . await ; // Reduced startup time
25+ tokio:: time:: sleep ( Duration :: from_millis ( 200 ) ) . await ;
3526
3627 Ok ( ( handle, port) )
3728}
3829
39- /// Get or initialize the shared benchmark server
40- fn get_benchmark_server_port ( ) -> u16 {
41- if let Some ( ( port, _) ) = BENCHMARK_SERVER . get ( ) {
42- * port
43- } else {
44- // Initialize server if not already done
45- let rt = Runtime :: new ( ) . unwrap ( ) ;
46- let ( _handle, port) = rt. block_on ( async {
47- setup_shared_benchmark_server ( ) . await . expect ( "Failed to setup shared server" )
48- } ) ;
49- port
50- }
51- }
52-
53- /// Helper function to make HTTP requests for benchmarking (with connection reuse)
30+ /// Helper function to make HTTP requests for benchmarking
5431async fn make_benchmark_request ( request : Value , port : u16 ) -> Result < Value , Box < dyn std:: error:: Error + Send + Sync > > {
55- static CLIENT : OnceLock < reqwest:: Client > = OnceLock :: new ( ) ;
56-
57- let client = CLIENT . get_or_init ( || {
58- reqwest:: Client :: builder ( )
59- . timeout ( Duration :: from_secs ( 5 ) ) // Shorter timeout for benchmarks
60- . pool_idle_timeout ( Duration :: from_secs ( 30 ) ) // Connection reuse
61- . build ( )
62- . unwrap ( )
63- } ) ;
64-
32+ let client = reqwest:: Client :: new ( ) ;
6533 let response = client
6634 . post ( format ! ( "http://localhost:{port}/api/mcp" ) )
6735 . header ( "Content-Type" , "application/json" )
@@ -76,7 +44,11 @@ async fn make_benchmark_request(request: Value, port: u16) -> Result<Value, Box<
7644/// Benchmark MCP protocol initialization
7745fn bench_mcp_initialization ( c : & mut Criterion ) {
7846 let rt = Runtime :: new ( ) . unwrap ( ) ;
79- let port = get_benchmark_server_port ( ) ;
47+
48+ // Setup server once for all benchmark iterations
49+ let ( _handle, port) = rt. block_on ( async {
50+ setup_benchmark_server ( ) . await . expect ( "Failed to setup server" )
51+ } ) ;
8052
8153 let initialize_request = json ! ( {
8254 "jsonrpc" : "2.0" ,
@@ -97,12 +69,15 @@ fn bench_mcp_initialization(c: &mut Criterion) {
9769 } ) ;
9870}
9971
100- /// Benchmark tools list retrieval
72+ /// Benchmark tools list retrieval
10173fn bench_tools_list ( c : & mut Criterion ) {
10274 let rt = Runtime :: new ( ) . unwrap ( ) ;
103- let port = get_benchmark_server_port ( ) ;
10475
105- // Initialize first (one time setup)
76+ let ( _handle, port) = rt. block_on ( async {
77+ setup_benchmark_server ( ) . await . expect ( "Failed to setup server" )
78+ } ) ;
79+
80+ // Initialize first
10681 let initialize_request = json ! ( {
10782 "jsonrpc" : "2.0" ,
10883 "id" : 1 ,
@@ -132,12 +107,15 @@ fn bench_tools_list(c: &mut Criterion) {
132107 } ) ;
133108}
134109
135- /// Benchmark different RPC tool calls (reduced scope for performance)
110+ /// Benchmark different RPC tool calls
136111fn bench_rpc_tool_calls ( c : & mut Criterion ) {
137112 let rt = Runtime :: new ( ) . unwrap ( ) ;
138- let port = get_benchmark_server_port ( ) ;
139113
140- // Initialize first (one time setup)
114+ let ( _handle, port) = rt. block_on ( async {
115+ setup_benchmark_server ( ) . await . expect ( "Failed to setup server" )
116+ } ) ;
117+
118+ // Initialize first
141119 let initialize_request = json ! ( {
142120 "jsonrpc" : "2.0" ,
143121 "id" : 1 ,
@@ -155,10 +133,12 @@ fn bench_rpc_tool_calls(c: &mut Criterion) {
155133
156134 let mut group = c. benchmark_group ( "rpc_tool_calls" ) ;
157135
158- // Benchmark only fast methods that don't require external network calls
136+ // Benchmark simple methods
159137 let simple_methods = vec ! [
160- ( "getVersion" , json!( { } ) ) , // Fast local method
161- ( "getSlot" , json!( { } ) ) , // Local cached data
138+ ( "getHealth" , json!( { } ) ) ,
139+ ( "getVersion" , json!( { } ) ) ,
140+ ( "getGenesisHash" , json!( { } ) ) ,
141+ ( "minimumLedgerSlot" , json!( { } ) ) ,
162142 ] ;
163143
164144 for ( method_name, params) in simple_methods {
@@ -180,15 +160,44 @@ fn bench_rpc_tool_calls(c: &mut Criterion) {
180160 } ) ;
181161 }
182162
163+ // Benchmark methods with parameters
164+ let param_methods = vec ! [
165+ ( "getBalance" , json!( { "pubkey" : "11111111111111111111111111111112" } ) ) ,
166+ ( "getAccountInfo" , json!( { "pubkey" : "11111111111111111111111111111112" } ) ) ,
167+ ( "getSlot" , json!( "{}" ) ) ,
168+ ] ;
169+
170+ for ( method_name, params) in param_methods {
171+ let request = json ! ( {
172+ "jsonrpc" : "2.0" ,
173+ "id" : 3 ,
174+ "method" : "tools/call" ,
175+ "params" : {
176+ "name" : method_name,
177+ "arguments" : params
178+ }
179+ } ) ;
180+
181+ group. bench_with_input ( BenchmarkId :: new ( "with_params" , method_name) , & request, |b, req| {
182+ b. to_async ( & rt) . iter ( || async {
183+ let result = make_benchmark_request ( black_box ( req. clone ( ) ) , port) . await ;
184+ black_box ( result)
185+ } )
186+ } ) ;
187+ }
188+
183189 group. finish ( ) ;
184190}
185191
186- /// Benchmark concurrent requests (reduced concurrency for faster benchmarks)
192+ /// Benchmark concurrent requests
187193fn bench_concurrent_requests ( c : & mut Criterion ) {
188194 let rt = Runtime :: new ( ) . unwrap ( ) ;
189- let port = get_benchmark_server_port ( ) ;
190195
191- // Initialize first (one time setup)
196+ let ( _handle, port) = rt. block_on ( async {
197+ setup_benchmark_server ( ) . await . expect ( "Failed to setup server" )
198+ } ) ;
199+
200+ // Initialize first
192201 let initialize_request = json ! ( {
193202 "jsonrpc" : "2.0" ,
194203 "id" : 1 ,
@@ -206,16 +215,15 @@ fn bench_concurrent_requests(c: &mut Criterion) {
206215
207216 let mut group = c. benchmark_group ( "concurrent_requests" ) ;
208217
209- // Test smaller concurrency levels for faster benchmarks
210- for concurrency in [ 1 , 5 , 10 ] . iter ( ) {
211- group. bench_with_input ( BenchmarkId :: new ( "getVersion" , concurrency) , concurrency, |b, & concurrency| {
218+ for concurrency in [ 1 , 5 , 10 , 20 ] . iter ( ) {
219+ group. bench_with_input ( BenchmarkId :: new ( "getHealth" , concurrency) , concurrency, |b, & concurrency| {
212220 b. to_async ( & rt) . iter ( || async {
213221 let request = json ! ( {
214222 "jsonrpc" : "2.0" ,
215223 "id" : 1 ,
216224 "method" : "tools/call" ,
217225 "params" : {
218- "name" : "getVersion" , // Use faster method
226+ "name" : "getHealth" ,
219227 "arguments" : { }
220228 }
221229 } ) ;
@@ -241,19 +249,14 @@ fn bench_concurrent_requests(c: &mut Criterion) {
241249/// Benchmark health endpoint
242250fn bench_health_endpoint ( c : & mut Criterion ) {
243251 let rt = Runtime :: new ( ) . unwrap ( ) ;
244- let port = get_benchmark_server_port ( ) ;
245-
246- static CLIENT : OnceLock < reqwest:: Client > = OnceLock :: new ( ) ;
247- let client = CLIENT . get_or_init ( || {
248- reqwest:: Client :: builder ( )
249- . timeout ( Duration :: from_secs ( 5 ) )
250- . pool_idle_timeout ( Duration :: from_secs ( 30 ) )
251- . build ( )
252- . unwrap ( )
252+
253+ let ( _handle, port) = rt. block_on ( async {
254+ setup_benchmark_server ( ) . await . expect ( "Failed to setup server" )
253255 } ) ;
254256
255257 c. bench_function ( "health_endpoint" , |b| {
256258 b. to_async ( & rt) . iter ( || async {
259+ let client = reqwest:: Client :: new ( ) ;
257260 let response = client
258261 . get ( format ! ( "http://localhost:{port}/health" ) )
259262 . send ( )
@@ -267,19 +270,14 @@ fn bench_health_endpoint(c: &mut Criterion) {
267270/// Benchmark metrics endpoint
268271fn bench_metrics_endpoint ( c : & mut Criterion ) {
269272 let rt = Runtime :: new ( ) . unwrap ( ) ;
270- let port = get_benchmark_server_port ( ) ;
271-
272- static CLIENT : OnceLock < reqwest:: Client > = OnceLock :: new ( ) ;
273- let client = CLIENT . get_or_init ( || {
274- reqwest:: Client :: builder ( )
275- . timeout ( Duration :: from_secs ( 5 ) )
276- . pool_idle_timeout ( Duration :: from_secs ( 30 ) )
277- . build ( )
278- . unwrap ( )
273+
274+ let ( _handle, port) = rt. block_on ( async {
275+ setup_benchmark_server ( ) . await . expect ( "Failed to setup server" )
279276 } ) ;
280277
281278 c. bench_function ( "metrics_endpoint" , |b| {
282279 b. to_async ( & rt) . iter ( || async {
280+ let client = reqwest:: Client :: new ( ) ;
283281 let response = client
284282 . get ( format ! ( "http://localhost:{port}/metrics" ) )
285283 . send ( )
0 commit comments