1
- use std:: { collections:: HashMap , fs:: File , io:: { BufWriter , Write } , net:: { SocketAddr , ToSocketAddrs } , sync:: atomic:: { AtomicU64 , Ordering :: Relaxed } , time:: { Duration , SystemTime } } ;
1
+ use std:: {
2
+ collections:: HashMap ,
3
+ fs:: File ,
4
+ io:: { BufWriter , Write } ,
5
+ net:: { SocketAddr , ToSocketAddrs } ,
6
+ sync:: atomic:: { AtomicU64 , Ordering :: Relaxed } ,
7
+ time:: { Duration , SystemTime } ,
8
+ } ;
2
9
3
10
use criterion:: { criterion_group, criterion_main, BenchmarkId , Criterion , Throughput } ;
4
11
use futures_util:: future;
5
12
use gotham:: {
6
- bind_server, handler:: FileOptions , router:: {
13
+ bind_server,
14
+ handler:: FileOptions ,
15
+ router:: {
7
16
build_simple_router,
8
17
builder:: { DefineSingleRoute , DrawRoutes } ,
9
- }
18
+ } ,
10
19
} ;
11
20
use tempfile:: TempDir ;
12
- use tokio:: { net:: TcpListener , runtime:: { self , Runtime } } ;
21
+ use tokio:: {
22
+ net:: TcpListener ,
23
+ runtime:: { self , Runtime } ,
24
+ } ;
13
25
14
26
struct BenchServer {
15
27
runtime : Runtime ,
@@ -25,22 +37,27 @@ impl BenchServer {
25
37
fn new ( ) -> anyhow:: Result < Self > {
26
38
let tmp = TempDir :: new ( ) ?;
27
39
// temporary datafiles
28
- let sizes = [ 10 , 17 , 24 ] . iter ( ) . filter_map ( |sz| {
29
- let size = 1 << sz;
30
- mk_tmp ( & tmp, size) . ok ( )
31
- } ) . collect ( ) ;
40
+ let sizes = [ 10 , 17 , 24 ]
41
+ . iter ( )
42
+ . filter_map ( |sz| {
43
+ let size = 1 << sz;
44
+ mk_tmp ( & tmp, size) . ok ( )
45
+ } )
46
+ . collect ( ) ;
32
47
let buf_paths = HashMap :: from ( [
33
48
( "default" . to_string ( ) , None ) ,
34
- ( "128k" . to_string ( ) , Some ( 1 << 17 ) )
49
+ ( "128k" . to_string ( ) , Some ( 1 << 17 ) ) ,
35
50
] ) ;
36
-
51
+
37
52
let router = build_simple_router ( |route| {
38
53
for ( path, sz) in & buf_paths {
39
54
let mut opts = FileOptions :: from ( tmp. path ( ) . to_owned ( ) ) ;
40
55
if let Some ( size) = sz {
41
56
opts. with_buffer_size ( * size) ;
42
57
}
43
- route. get ( format ! ( "/{path}/*" ) . as_str ( ) ) . to_dir ( opts. to_owned ( ) )
58
+ route
59
+ . get ( format ! ( "/{path}/*" ) . as_str ( ) )
60
+ . to_dir ( opts. to_owned ( ) )
44
61
}
45
62
} ) ;
46
63
let runtime = runtime:: Builder :: new_multi_thread ( )
@@ -54,11 +71,17 @@ impl BenchServer {
54
71
let listener = runtime. block_on ( TcpListener :: bind ( addr) ) . unwrap ( ) ;
55
72
// use any free port
56
73
let addr = listener. local_addr ( ) . unwrap ( ) ;
57
- let _ = runtime. spawn ( async move {
74
+ let _ = runtime. spawn ( async move {
58
75
bind_server ( listener, router, future:: ok) . await ;
59
76
} ) ;
60
77
std:: thread:: sleep ( Duration :: from_millis ( 100 ) ) ;
61
- Ok ( Self { runtime, addr, tmp, sizes, buf_paths } )
78
+ Ok ( Self {
79
+ runtime,
80
+ addr,
81
+ tmp,
82
+ sizes,
83
+ buf_paths,
84
+ } )
62
85
}
63
86
}
64
87
@@ -67,7 +90,11 @@ fn mk_tmp(tmp: &TempDir, size: u64) -> anyhow::Result<u64> {
67
90
let file = File :: create ( filename) ?;
68
91
let mut w = BufWriter :: with_capacity ( 2 << 16 , file) ;
69
92
// pseudo random data: time stamp as bytes
70
- let ts_data = SystemTime :: now ( ) . duration_since ( SystemTime :: UNIX_EPOCH ) . unwrap ( ) . as_nanos ( ) . to_le_bytes ( ) ;
93
+ let ts_data = SystemTime :: now ( )
94
+ . duration_since ( SystemTime :: UNIX_EPOCH )
95
+ . unwrap ( )
96
+ . as_nanos ( )
97
+ . to_le_bytes ( ) ;
71
98
for _ in ( 0 ..size) . step_by ( ts_data. len ( ) ) {
72
99
w. write_all ( & ts_data) ?;
73
100
}
@@ -88,27 +115,35 @@ pub fn filehandler_benchmark(c: &mut Criterion) {
88
115
for ( path, buf_size) in & server. buf_paths {
89
116
let url = format ! ( "http://{}/{path}/{file_size}" , server. addr) ;
90
117
let req = client. get ( url) . build ( ) . unwrap ( ) ;
91
- group. bench_with_input ( BenchmarkId :: new ( "test_file_handler" ,
92
- format ! ( "filesize: {file_size}, bufsize: {buf_size:?}" ) ) , & req, |b, req| {
93
- b. to_async ( & runtime) . iter ( || async {
118
+ group. bench_with_input (
119
+ BenchmarkId :: new (
120
+ "test_file_handler" ,
121
+ format ! ( "filesize: {file_size}, bufsize: {buf_size:?}" ) ,
122
+ ) ,
123
+ & req,
124
+ |b, req| {
125
+ b. to_async ( & runtime) . iter ( || async {
94
126
let r = client. execute ( req. try_clone ( ) . unwrap ( ) ) . await ;
95
127
counter. fetch_add ( 1 , Relaxed ) ;
96
128
match r {
97
- Err ( _) => { failed. fetch_add ( 1 , Relaxed ) ; } ,
129
+ Err ( _) => {
130
+ failed. fetch_add ( 1 , Relaxed ) ;
131
+ }
98
132
Ok ( res) => {
99
133
// sanity check: did we get what was expected?
100
134
assert_eq ! ( res. content_length( ) . unwrap( ) , file_size) ;
101
135
let _ = res. bytes ( ) . await . unwrap ( ) ;
102
136
}
103
137
}
104
- } ) ;
105
- } ) ;
138
+ } ) ;
139
+ } ,
140
+ ) ;
106
141
}
107
142
}
108
143
println ! ( "Errors {}/{}" , failed. load( Relaxed ) , counter. load( Relaxed ) ) ;
109
144
}
110
145
111
- criterion_group ! {
146
+ criterion_group ! {
112
147
name = file_handler;
113
148
config = Criterion :: default ( ) . measurement_time( Duration :: from_millis( 10_000 ) ) . warm_up_time( Duration :: from_millis( 10 ) ) ;
114
149
targets = filehandler_benchmark
0 commit comments