@@ -11,144 +11,164 @@ use std::net::SocketAddr;
1111
1212use futures:: { Future , Stream } ;
1313use tokio:: runtime:: current_thread:: Runtime ;
14- use tokio:: net:: TcpListener ;
1514
16- use hyper:: { Body , Method , Request , Response , Version } ;
15+ use hyper:: { Body , Method , Request , Response , Server } ;
1716use hyper:: client:: HttpConnector ;
18- use hyper:: server:: conn:: Http ;
1917
2018#[ bench]
2119fn http1_get ( b : & mut test:: Bencher ) {
22- bench_with ( b, Version :: HTTP_11 , || {
23- Request :: new ( Body :: empty ( ) )
24- } ) ;
20+ opts ( )
21+ . bench ( b)
2522}
2623
2724#[ bench]
2825fn http1_post ( b : & mut test:: Bencher ) {
29- bench_with ( b, Version :: HTTP_11 , || {
30- let mut req = Request :: new ( "foo bar baz quux" . into ( ) ) ;
31- * req. method_mut ( ) = Method :: POST ;
32- req
33- } ) ;
26+ opts ( )
27+ . method ( Method :: POST )
28+ . request_body ( b"foo bar baz quux" )
29+ . bench ( b)
3430}
3531
3632#[ bench]
3733fn http1_get_parallel ( b : & mut test:: Bencher ) {
38- bench_parallel_with ( b , Version :: HTTP_11 , || {
39- Request :: new ( Body :: empty ( ) )
40- } ) ;
34+ opts ( )
35+ . parallel ( 10 )
36+ . bench ( b )
4137}
4238
4339#[ bench]
4440fn http2_get ( b : & mut test:: Bencher ) {
45- bench_with ( b , Version :: HTTP_2 , || {
46- Request :: new ( Body :: empty ( ) )
47- } ) ;
41+ opts ( )
42+ . http2 ( )
43+ . bench ( b )
4844}
4945
5046#[ bench]
5147fn http2_post ( b : & mut test:: Bencher ) {
52- bench_with ( b , Version :: HTTP_2 , || {
53- let mut req = Request :: new ( "foo bar baz quux" . into ( ) ) ;
54- * req . method_mut ( ) = Method :: POST ;
55- req
56- } ) ;
48+ opts ( )
49+ . http2 ( )
50+ . method ( Method :: POST )
51+ . request_body ( b"foo bar baz quux" )
52+ . bench ( b )
5753}
5854
5955#[ bench]
6056fn http2_get_parallel ( b : & mut test:: Bencher ) {
61- bench_parallel_with ( b, Version :: HTTP_2 , || {
62- Request :: new ( Body :: empty ( ) )
63- } ) ;
57+ opts ( )
58+ . http2 ( )
59+ . parallel ( 10 )
60+ . bench ( b)
6461}
6562
66- fn bench_with < F > ( b : & mut test:: Bencher , version : Version , make_request : F )
67- where
68- F : Fn ( ) -> Request < Body > ,
69- {
70- let _ = pretty_env_logger:: try_init ( ) ;
71- let mut rt = Runtime :: new ( ) . unwrap ( ) ;
72- let body = b"Hello" ;
73- let addr = spawn_hello ( & mut rt, body) ;
74-
75- let connector = HttpConnector :: new ( 1 ) ;
76- let client = hyper:: Client :: builder ( )
77- . http2_only ( version == Version :: HTTP_2 )
78- . build :: < _ , Body > ( connector) ;
79-
80- let url: hyper:: Uri = format ! ( "http://{}/hello" , addr) . parse ( ) . unwrap ( ) ;
81-
82- b. bytes = body. len ( ) as u64 ;
83- b. iter ( move || {
84- let mut req = make_request ( ) ;
85- * req. uri_mut ( ) = url. clone ( ) ;
86- rt. block_on ( client. request ( req) . and_then ( |res| {
87- res. into_body ( ) . for_each ( |_chunk| {
88- Ok ( ( ) )
89- } )
90- } ) ) . expect ( "client wait" ) ;
91- } ) ;
63+ // ==== Benchmark Options =====
64+
65+ struct Opts {
66+ http2 : bool ,
67+ parallel_cnt : u32 ,
68+ request_method : Method ,
69+ request_body : Option < & ' static [ u8 ] > ,
70+ response_body : & ' static [ u8 ] ,
71+ }
72+
73+ fn opts ( ) -> Opts {
74+ Opts {
75+ http2 : false ,
76+ parallel_cnt : 1 ,
77+ request_method : Method :: GET ,
78+ request_body : None ,
79+ response_body : b"Hello" ,
80+ }
9281}
9382
94- fn bench_parallel_with < F > ( b : & mut test:: Bencher , version : Version , make_request : F )
95- where
96- F : Fn ( ) -> Request < Body > ,
97- {
98- let _ = pretty_env_logger:: try_init ( ) ;
99- let mut rt = Runtime :: new ( ) . unwrap ( ) ;
100- let body = b"Hello" ;
101- let addr = spawn_hello ( & mut rt, body) ;
102-
103- let connector = HttpConnector :: new ( 1 ) ;
104- let client = hyper:: Client :: builder ( )
105- . http2_only ( version == Version :: HTTP_2 )
106- . build :: < _ , Body > ( connector) ;
107-
108- let url: hyper:: Uri = format ! ( "http://{}/hello" , addr) . parse ( ) . unwrap ( ) ;
109-
110- b. bytes = body. len ( ) as u64 ;
111- b. iter ( move || {
112- let futs = ( 0 ..10 )
113- . into_iter ( )
114- . map ( |_| {
83+ impl Opts {
84+ fn http2 ( mut self ) -> Self {
85+ self . http2 = true ;
86+ self
87+ }
88+
89+ fn method ( mut self , m : Method ) -> Self {
90+ self . request_method = m;
91+ self
92+ }
93+
94+ fn request_body ( mut self , body : & ' static [ u8 ] ) -> Self {
95+ self . request_body = Some ( body) ;
96+ self
97+ }
98+
99+ fn parallel ( mut self , cnt : u32 ) -> Self {
100+ assert ! ( cnt > 0 , "parallel count must be larger than 0" ) ;
101+ self . parallel_cnt = cnt;
102+ self
103+ }
104+
105+ fn bench ( self , b : & mut test:: Bencher ) {
106+ let _ = pretty_env_logger:: try_init ( ) ;
107+ let mut rt = Runtime :: new ( ) . unwrap ( ) ;
108+ let addr = spawn_hello ( & mut rt, self . response_body ) ;
109+
110+ let connector = HttpConnector :: new ( 1 ) ;
111+ let client = hyper:: Client :: builder ( )
112+ . http2_only ( self . http2 )
113+ . build :: < _ , Body > ( connector) ;
114+
115+ let url: hyper:: Uri = format ! ( "http://{}/hello" , addr) . parse ( ) . unwrap ( ) ;
116+
117+ let make_request = || {
118+ let body = self
119+ . request_body
120+ . map ( Body :: from)
121+ . unwrap_or_else ( || Body :: empty ( ) ) ;
122+ let mut req = Request :: new ( body) ;
123+ * req. method_mut ( ) = self . request_method . clone ( ) ;
124+ req
125+ } ;
126+
127+ if self . parallel_cnt == 1 {
128+ b. iter ( move || {
115129 let mut req = make_request ( ) ;
116130 * req. uri_mut ( ) = url. clone ( ) ;
117- client. request ( req) . and_then ( |res| {
131+ rt . block_on ( client. request ( req) . and_then ( |res| {
118132 res. into_body ( ) . for_each ( |_chunk| {
119133 Ok ( ( ) )
120134 } )
121- } ) . map_err ( |_e| ( ) )
135+ } ) ) . expect ( "client wait" ) ;
122136 } ) ;
123- let _ = rt. block_on ( :: futures:: future:: join_all ( futs) ) ;
124- } ) ;
137+ } else {
138+ b. iter ( || {
139+ let futs = ( 0 ..self . parallel_cnt )
140+ . into_iter ( )
141+ . map ( |_| {
142+ let mut req = make_request ( ) ;
143+ * req. uri_mut ( ) = url. clone ( ) ;
144+ client. request ( req) . and_then ( |res| {
145+ res. into_body ( ) . for_each ( |_chunk| {
146+ Ok ( ( ) )
147+ } )
148+ } ) . map_err ( |e| panic ! ( "client error: {}" , e) )
149+ } ) ;
150+ let _ = rt. block_on ( :: futures:: future:: join_all ( futs) ) ;
151+ } ) ;
152+ }
153+ }
125154}
126155
127156fn spawn_hello ( rt : & mut Runtime , body : & ' static [ u8 ] ) -> SocketAddr {
128157 use hyper:: service:: { service_fn} ;
129158 let addr = "127.0.0.1:0" . parse ( ) . unwrap ( ) ;
130- let listener = TcpListener :: bind ( & addr) . unwrap ( ) ;
131- let addr = listener. local_addr ( ) . unwrap ( ) ;
132-
133- let http = Http :: new ( ) ;
134159
135- let service = service_fn ( move |req : Request < Body > | {
136- req. into_body ( )
137- . concat2 ( )
138- . map ( move |_| {
139- Response :: new ( Body :: from ( body) )
160+ let srv = Server :: bind ( & addr)
161+ . serve ( move || {
162+ service_fn ( move |req : Request < Body > | {
163+ req. into_body ( )
164+ . concat2 ( )
165+ . map ( move |_| {
166+ Response :: new ( Body :: from ( body) )
167+ } )
140168 } )
141- } ) ;
142-
143- // Specifically only accept 1 connection.
144- let srv = listener. incoming ( )
145- . into_future ( )
146- . map_err ( |( e, _inc) | panic ! ( "accept error: {}" , e) )
147- . and_then ( move |( accepted, _inc) | {
148- let socket = accepted. expect ( "accepted socket" ) ;
149- http. serve_connection ( socket, service)
150- . map_err ( |_| ( ) )
151169 } ) ;
152- rt. spawn ( srv) ;
170+ let addr = srv. local_addr ( ) ;
171+ let fut = srv. map_err ( |err| panic ! ( "server error: {}" , err) ) ;
172+ rt. spawn ( fut) ;
153173 return addr
154174}
0 commit comments