@@ -12,6 +12,7 @@ use std::fmt;
1212use std:: io:: Cursor ;
1313
1414type EncodeBuf < ' a > = bytes:: buf:: Limit < & ' a mut BytesMut > ;
15+
1516/// Header frame
1617///
1718/// This could be either a request or a response.
@@ -87,6 +88,9 @@ struct HeaderBlock {
8788 /// The decoded header fields
8889 fields : HeaderMap ,
8990
91+ /// Precomputed size of all of our header fields, for perf reasons
92+ field_size : usize ,
93+
9094 /// Set to true if decoding went over the max header list size.
9195 is_over_size : bool ,
9296
@@ -115,6 +119,7 @@ impl Headers {
115119 stream_id,
116120 stream_dep : None ,
117121 header_block : HeaderBlock {
122+ field_size : calculate_headermap_size ( & fields) ,
118123 fields,
119124 is_over_size : false ,
120125 pseudo,
@@ -131,6 +136,7 @@ impl Headers {
131136 stream_id,
132137 stream_dep : None ,
133138 header_block : HeaderBlock {
139+ field_size : calculate_headermap_size ( & fields) ,
134140 fields,
135141 is_over_size : false ,
136142 pseudo : Pseudo :: default ( ) ,
@@ -196,6 +202,7 @@ impl Headers {
196202 stream_dep,
197203 header_block : HeaderBlock {
198204 fields : HeaderMap :: new ( ) ,
205+ field_size : 0 ,
199206 is_over_size : false ,
200207 pseudo : Pseudo :: default ( ) ,
201208 } ,
@@ -350,6 +357,7 @@ impl PushPromise {
350357 PushPromise {
351358 flags : PushPromiseFlag :: default ( ) ,
352359 header_block : HeaderBlock {
360+ field_size : calculate_headermap_size ( & fields) ,
353361 fields,
354362 is_over_size : false ,
355363 pseudo,
@@ -441,6 +449,7 @@ impl PushPromise {
441449 flags,
442450 header_block : HeaderBlock {
443451 fields : HeaderMap :: new ( ) ,
452+ field_size : 0 ,
444453 is_over_size : false ,
445454 pseudo : Pseudo :: default ( ) ,
446455 } ,
@@ -892,6 +901,8 @@ impl HeaderBlock {
892901
893902 headers_size += decoded_header_size ( name. as_str ( ) . len ( ) , value. len ( ) ) ;
894903 if headers_size < max_header_list_size {
904+ self . field_size +=
905+ decoded_header_size ( name. as_str ( ) . len ( ) , value. len ( ) ) ;
895906 self . fields . append ( name, value) ;
896907 } else if !self . is_over_size {
897908 tracing:: trace!( "load_hpack; header list size over max" ) ;
@@ -958,14 +969,16 @@ impl HeaderBlock {
958969 + pseudo_size ! ( status)
959970 + pseudo_size ! ( authority)
960971 + pseudo_size ! ( path)
961- + self
962- . fields
963- . iter ( )
964- . map ( |( name, value) | decoded_header_size ( name. as_str ( ) . len ( ) , value. len ( ) ) )
965- . sum :: < usize > ( )
972+ + self . field_size
966973 }
967974}
968975
976+ fn calculate_headermap_size ( map : & HeaderMap ) -> usize {
977+ map. iter ( )
978+ . map ( |( name, value) | decoded_header_size ( name. as_str ( ) . len ( ) , value. len ( ) ) )
979+ . sum :: < usize > ( )
980+ }
981+
969982fn decoded_header_size ( name : usize , value : usize ) -> usize {
970983 name + value + 32
971984}
0 commit comments