@@ -83,9 +83,112 @@ fn resp_short(c: &mut Criterion) {
8383 } ) ) ;
8484}
8585
86+ fn uri ( c : & mut Criterion ) {
87+ fn _uri ( c : & mut Criterion , name : & str , input : & ' static [ u8 ] ) {
88+ c. benchmark_group ( "uri" )
89+ . throughput ( Throughput :: Bytes ( input. len ( ) as u64 ) )
90+ . bench_function ( name, |b| b. iter ( || {
91+ black_box ( {
92+ let mut b = httparse:: _benchable:: Bytes :: new ( input) ;
93+ httparse:: _benchable:: parse_uri ( & mut b) . unwrap ( )
94+ } ) ;
95+ } ) ) ;
96+ }
97+
98+ const S : & [ u8 ] = b" " ;
99+ const CHUNK64 : & [ u8 ] = b"/wp-content/uploads/2022/08/31/hello-kitty-darth-vader-pink.webp" ;
100+ let chunk_4k = CHUNK64 . repeat ( 64 ) ;
101+
102+ // 1b to 4096b
103+ for p in 0 ..=12 {
104+ let n = 1 << p;
105+ _uri ( c, & format ! ( "uri_{}b" , n) , [ chunk_4k[ ..n] . to_vec ( ) , S . into ( ) ] . concat ( ) . leak ( ) ) ;
106+ }
107+ }
108+
109+ fn header ( c : & mut Criterion ) {
110+ fn _header ( c : & mut Criterion , name : & str , input : & ' static [ u8 ] ) {
111+ let mut headers = [ httparse:: EMPTY_HEADER ; 128 ] ;
112+ c. benchmark_group ( "header" )
113+ . throughput ( Throughput :: Bytes ( input. len ( ) as u64 ) )
114+ . bench_function ( name, |b| b. iter ( || {
115+ black_box ( {
116+ let _ = httparse:: parse_headers ( input, & mut headers) . unwrap ( ) ;
117+ } ) ;
118+ } ) ) ;
119+ }
120+
121+ const RN : & [ u8 ] = b"\r \n " ;
122+ const RNRN : & [ u8 ] = b"\r \n \r \n " ;
123+ const TINY_RN : & [ u8 ] = b"a: b\r \n " ; // minimal header line
124+ const XFOOBAR : & [ u8 ] = b"X-Foobar" ;
125+ let xfoobar_4k = XFOOBAR . repeat ( 4096 /XFOOBAR . len ( ) ) ;
126+
127+ // header names 1b to 4096b
128+ for p in 0 ..=12 {
129+ let n = 1 << p;
130+ let payload = [ & xfoobar_4k[ ..n] , b": b" , RNRN ] . concat ( ) . leak ( ) ;
131+ _header ( c, & format ! ( "name_{}b" , n) , payload) ;
132+ }
133+
134+ // header values 1b to 4096b
135+ for p in 0 ..=12 {
136+ let n = 1 << p;
137+ let payload = [ b"a: " , & xfoobar_4k[ ..n] , RNRN ] . concat ( ) . leak ( ) ;
138+ _header ( c, & format ! ( "value_{}b" , n) , payload) ;
139+ }
140+
141+ // 1 to 128
142+ for p in 0 ..=7 {
143+ let n = 1 << p;
144+ _header ( c, & format ! ( "count_{}" , n) , [ TINY_RN . repeat ( n) , RN . into ( ) ] . concat ( ) . leak ( ) ) ;
145+ }
146+ }
147+
148+ fn version ( c : & mut Criterion ) {
149+ fn _version ( c : & mut Criterion , name : & str , input : & ' static [ u8 ] ) {
150+ c. benchmark_group ( "version" )
151+ . throughput ( Throughput :: Bytes ( input. len ( ) as u64 ) )
152+ . bench_function ( name, |b| b. iter ( || {
153+ black_box ( {
154+ let mut b = httparse:: _benchable:: Bytes :: new ( input) ;
155+ httparse:: _benchable:: parse_version ( & mut b) . unwrap ( )
156+ } ) ;
157+ } ) ) ;
158+ }
159+
160+ _version ( c, "http10" , b"HTTP/1.0\r \n " ) ;
161+ _version ( c, "http11" , b"HTTP/1.1\r \n " ) ;
162+ _version ( c, "partial" , b"HTTP/1." ) ;
163+ }
164+
165+ fn method ( c : & mut Criterion ) {
166+ fn _method ( c : & mut Criterion , name : & str , input : & ' static [ u8 ] ) {
167+ c. benchmark_group ( "method" )
168+ . throughput ( Throughput :: Bytes ( input. len ( ) as u64 ) )
169+ . bench_function ( name, |b| b. iter ( || {
170+ black_box ( {
171+ let mut b = httparse:: _benchable:: Bytes :: new ( input) ;
172+ httparse:: _benchable:: parse_method ( & mut b) . unwrap ( )
173+ } ) ;
174+ } ) ) ;
175+ }
176+
177+ // Common methods should be fast-pathed
178+ const COMMON_METHODS : & [ & str ] = & [ "GET" , "HEAD" , "POST" , "PUT" , "DELETE" , "CONNECT" , "OPTIONS" , "TRACE" , "PATCH" ] ;
179+ for method in COMMON_METHODS {
180+ _method ( c, & method. to_lowercase ( ) , format ! ( "{} / HTTP/1.1\r \n " , method) . into_bytes ( ) . leak ( ) ) ;
181+ }
182+ // Custom methods should be infrequent and thus not worth optimizing
183+ _method ( c, "custom" , b"CUSTOM / HTTP/1.1\r \n " ) ;
184+ }
185+
186+ const WARMUP : Duration = Duration :: from_millis ( 100 ) ;
187+ const MTIME : Duration = Duration :: from_millis ( 100 ) ;
188+ const SAMPLES : usize = 200 ;
86189criterion_group ! {
87190 name = benches;
88- config = Criterion :: default ( ) . sample_size( 100 ) . measurement_time ( Duration :: from_secs ( 10 ) ) ;
89- targets = req, req_short, resp, resp_short
191+ config = Criterion :: default ( ) . sample_size( SAMPLES ) . warm_up_time ( WARMUP ) . measurement_time ( MTIME ) ;
192+ targets = req, req_short, resp, resp_short, uri , header , version , method
90193}
91194criterion_main ! ( benches) ;
0 commit comments