Skip to content

Commit c0bd775

Browse files
Noah-Kennedyseanmonstar
authored andcommitted
perf: optimize header list size calculations (#750)
This speeds up loading blocks in cases where we have many headers already.
1 parent e5db9a3 commit c0bd775

File tree

3 files changed

+19
-6
lines changed

3 files changed

+19
-6
lines changed

.github/workflows/CI.yml

-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ jobs:
3131
strategy:
3232
matrix:
3333
rust:
34-
- nightly
3534
- beta
3635
- stable
3736
steps:

src/frame/headers.rs

+18-5
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use std::fmt;
1212
use std::io::Cursor;
1313

1414
type 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+
969982
fn decoded_header_size(name: usize, value: usize) -> usize {
970983
name + value + 32
971984
}

src/proto/streams/store.rs

+1
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ impl Store {
127127
}
128128
}
129129

130+
#[allow(clippy::blocks_in_conditions)]
130131
pub(crate) fn for_each<F>(&mut self, mut f: F)
131132
where
132133
F: FnMut(Ptr),

0 commit comments

Comments
 (0)