1
- use std:: {
2
- collections:: HashMap ,
3
- future:: IntoFuture ,
4
- io:: Write ,
5
- net:: { IpAddr , Ipv4Addr , SocketAddr } ,
6
- path:: PathBuf ,
7
- time:: Duration ,
1
+ use {
2
+ agave_thread_manager:: * ,
3
+ log:: { debug, info} ,
4
+ std:: {
5
+ collections:: HashMap ,
6
+ future:: IntoFuture ,
7
+ io:: Write ,
8
+ net:: { IpAddr , Ipv4Addr , SocketAddr } ,
9
+ path:: PathBuf ,
10
+ time:: Duration ,
11
+ } ,
8
12
} ;
9
13
10
14
async fn axum_main ( port : u16 ) {
11
15
use axum:: { routing:: get, Router } ;
12
-
13
16
// basic handler that responds with a static string
14
17
async fn root ( ) -> & ' static str {
15
18
tokio:: time:: sleep ( Duration :: from_millis ( 1 ) ) . await ;
@@ -24,6 +27,7 @@ async fn axum_main(port: u16) {
24
27
tokio:: net:: TcpListener :: bind ( SocketAddr :: new ( IpAddr :: V4 ( Ipv4Addr :: UNSPECIFIED ) , port) )
25
28
. await
26
29
. unwrap ( ) ;
30
+ info ! ( "Server on port {port} ready" ) ;
27
31
let timeout = tokio:: time:: timeout (
28
32
Duration :: from_secs ( 11 ) ,
29
33
axum:: serve ( listener, app) . into_future ( ) ,
@@ -32,11 +36,10 @@ async fn axum_main(port: u16) {
32
36
match timeout {
33
37
Ok ( v) => v. unwrap ( ) ,
34
38
Err ( _) => {
35
- println ! ( "Terminating server on port {port}" ) ;
39
+ info ! ( "Terminating server on port {port}" ) ;
36
40
}
37
41
}
38
42
}
39
- use agave_thread_manager:: * ;
40
43
fn make_config_shared ( cc : usize ) -> RuntimeManagerConfig {
41
44
let tokio_cfg_1 = TokioConfig {
42
45
core_allocation : CoreAllocation :: DedicatedCoreSet { min : 0 , max : cc } ,
@@ -46,12 +49,8 @@ fn make_config_shared(cc: usize) -> RuntimeManagerConfig {
46
49
let tokio_cfg_2 = tokio_cfg_1. clone ( ) ;
47
50
RuntimeManagerConfig {
48
51
tokio_configs : HashMap :: from ( [
49
- ( "tokio1" . into ( ) , tokio_cfg_1) ,
50
- ( "tokio2" . into ( ) , tokio_cfg_2) ,
51
- ] ) ,
52
- tokio_runtime_mapping : HashMap :: from ( [
53
- ( "axum1" . into ( ) , "tokio1" . into ( ) ) ,
54
- ( "axum2" . into ( ) , "tokio2" . into ( ) ) ,
52
+ ( "axum1" . into ( ) , tokio_cfg_1) ,
53
+ ( "axum2" . into ( ) , tokio_cfg_2) ,
55
54
] ) ,
56
55
..Default :: default ( )
57
56
}
@@ -75,12 +74,8 @@ fn make_config_dedicated(cc: usize) -> RuntimeManagerConfig {
75
74
} ;
76
75
RuntimeManagerConfig {
77
76
tokio_configs : HashMap :: from ( [
78
- ( "tokio1" . into ( ) , tokio_cfg_1) ,
79
- ( "tokio2" . into ( ) , tokio_cfg_2) ,
80
- ] ) ,
81
- tokio_runtime_mapping : HashMap :: from ( [
82
- ( "axum1" . into ( ) , "tokio1" . into ( ) ) ,
83
- ( "axum2" . into ( ) , "tokio2" . into ( ) ) ,
77
+ ( "axum1" . into ( ) , tokio_cfg_1) ,
78
+ ( "axum2" . into ( ) , tokio_cfg_2) ,
84
79
] ) ,
85
80
..Default :: default ( )
86
81
}
@@ -93,7 +88,7 @@ enum Regime {
93
88
Single ,
94
89
}
95
90
impl Regime {
96
- const VALUES : [ Self ; 3 ] = [ Self :: Shared , Self :: Dedicated , Self :: Single ] ;
91
+ const VALUES : [ Self ; 3 ] = [ Self :: Dedicated , Self :: Shared , Self :: Single ] ;
97
92
}
98
93
99
94
#[ derive( Debug , Default , serde:: Serialize ) ]
@@ -103,13 +98,14 @@ struct Results {
103
98
}
104
99
105
100
fn main ( ) -> anyhow:: Result < ( ) > {
101
+ env_logger:: Builder :: from_env ( env_logger:: Env :: default ( ) . default_filter_or ( "info" ) ) . init ( ) ;
106
102
let mut all_results: HashMap < String , Results > = HashMap :: new ( ) ;
107
103
for regime in Regime :: VALUES {
108
104
let mut res = Results :: default ( ) ;
109
105
for core_cnt in [ 2 , 4 , 8 , 16 ] {
110
106
let rtm;
111
- println ! ( "===================" ) ;
112
- println ! ( "Running {core_cnt} cores under {regime:?}" ) ;
107
+ info ! ( "===================" ) ;
108
+ info ! ( "Running {core_cnt} cores under {regime:?}" ) ;
113
109
let ( tok1, tok2) = match regime {
114
110
Regime :: Shared => {
115
111
rtm = ThreadManager :: new ( make_config_shared ( core_cnt) ) . unwrap ( ) ;
@@ -143,24 +139,26 @@ fn main() -> anyhow::Result<()> {
143
139
let wrk_cores: Vec < _ > = ( 32 ..64 ) . collect ( ) ;
144
140
let results = std:: thread:: scope ( |s| {
145
141
s. spawn ( || {
146
- tok1. tokio . spawn ( axum_main ( 8888 ) ) ;
142
+ tok1. start_metrics_sampling ( Duration :: from_secs ( 1 ) ) ;
143
+ tok1. tokio . block_on ( axum_main ( 8888 ) ) ;
147
144
} ) ;
148
145
let jh = match regime {
149
146
Regime :: Single => s. spawn ( || {
150
- run_wrk ( & [ 8888 , 8888 ] , & wrk_cores, wrk_cores. len ( ) , 1000 ) . unwrap ( )
147
+ run_wrk ( & [ 8888 , 8888 ] , & wrk_cores, wrk_cores. len ( ) , 3000 ) . unwrap ( )
151
148
} ) ,
152
149
_ => {
153
150
s. spawn ( || {
154
- tok2. tokio . spawn ( axum_main ( 8889 ) ) ;
151
+ tok2. start_metrics_sampling ( Duration :: from_secs ( 1 ) ) ;
152
+ tok2. tokio . block_on ( axum_main ( 8889 ) ) ;
155
153
} ) ;
156
154
s. spawn ( || {
157
- run_wrk ( & [ 8888 , 8889 ] , & wrk_cores, wrk_cores. len ( ) , 1000 ) . unwrap ( )
155
+ run_wrk ( & [ 8888 , 8889 ] , & wrk_cores, wrk_cores. len ( ) , 3000 ) . unwrap ( )
158
156
} )
159
157
}
160
158
} ;
161
159
jh. join ( ) . expect ( "WRK crashed!" )
162
160
} ) ;
163
- println ! ( "Results are: {:?}" , results) ;
161
+ info ! ( "Results are: {:?}" , results) ;
164
162
res. latencies_s . push (
165
163
results. 0 . iter ( ) . map ( |a| a. as_secs_f32 ( ) ) . sum :: < f32 > ( ) / results. 0 . len ( ) as f32 ,
166
164
) ;
@@ -169,6 +167,8 @@ fn main() -> anyhow::Result<()> {
169
167
all_results. insert ( format ! ( "{regime:?}" ) , res) ;
170
168
std:: thread:: sleep ( Duration :: from_secs ( 3 ) ) ;
171
169
}
170
+
171
+ //print the resulting measurements so they can be e.g. plotted with matplotlib
172
172
println ! ( "{}" , serde_json:: to_string_pretty( & all_results) ?) ;
173
173
174
174
Ok ( ( ) )
@@ -180,6 +180,9 @@ fn run_wrk(
180
180
threads : usize ,
181
181
connections : usize ,
182
182
) -> anyhow:: Result < ( Vec < Duration > , Vec < f32 > ) > {
183
+ //Sleep a bit to let axum start
184
+ std:: thread:: sleep ( Duration :: from_millis ( 500 ) ) ;
185
+
183
186
let mut script = PathBuf :: from ( env ! ( "CARGO_MANIFEST_DIR" ) ) ;
184
187
script. push ( "examples/report.lua" ) ;
185
188
let cpus: Vec < String > = cpus. iter ( ) . map ( |c| c. to_string ( ) ) . collect ( ) ;
@@ -209,7 +212,7 @@ fn run_wrk(
209
212
let mut all_latencies = vec ! [ ] ;
210
213
let mut all_rps = vec ! [ ] ;
211
214
for ( out, port) in outs. zip ( ports. iter ( ) ) {
212
- println ! ( "=========================" ) ;
215
+ debug ! ( "=========================" ) ;
213
216
std:: io:: stdout ( ) . write_all ( & out. stderr ) ?;
214
217
let res = str:: from_utf8 ( & out. stdout ) ?;
215
218
let mut res = res. lines ( ) . last ( ) . unwrap ( ) . split ( ' ' ) ;
@@ -219,7 +222,7 @@ fn run_wrk(
219
222
220
223
let requests: usize = res. next ( ) . unwrap ( ) . parse ( ) ?;
221
224
let rps = requests as f32 / 10.0 ;
222
- println ! ( "WRK results for port {port}: {latency:?} {rps}" ) ;
225
+ debug ! ( "WRK results for port {port}: {latency:?} {rps}" ) ;
223
226
all_latencies. push ( Duration :: from_micros ( latency_us) ) ;
224
227
all_rps. push ( rps) ;
225
228
}
0 commit comments