diff --git a/src/header/internals/cell.rs b/src/header/internals/cell.rs index 59597d49..21ded572 100644 --- a/src/header/internals/cell.rs +++ b/src/header/internals/cell.rs @@ -58,6 +58,11 @@ impl PtrMapCell { PtrMapCell(UnsafeCell::new(PtrMap::Empty)) } + #[inline] + pub fn with_one(key: TypeId, val: Box) -> PtrMapCell { + PtrMapCell(UnsafeCell::new(PtrMap::One(key, val))) + } + #[inline] pub fn get(&self, key: TypeId) -> Option<&V> { let map = unsafe { &*self.0.get() }; diff --git a/src/header/internals/item.rs b/src/header/internals/item.rs index 0ceb1119..b150cd39 100644 --- a/src/header/internals/item.rs +++ b/src/header/internals/item.rs @@ -23,12 +23,11 @@ impl Item { } #[inline] - pub fn new_typed(ty: Box
) -> Item { - let map = PtrMapCell::new(); - unsafe { map.insert((*ty).get_type(), ty); } + + pub fn new_typed(val: H) -> Item { Item { raw: OptCell::new(None), - typed: map, + typed: PtrMapCell::with_one(TypeId::of::(), Box::new(val)), } } diff --git a/src/header/mod.rs b/src/header/mod.rs index dfe96ec6..60b7ee64 100644 --- a/src/header/mod.rs +++ b/src/header/mod.rs @@ -344,6 +344,7 @@ macro_rules! literals { _ => () } + trace!("maybe_literal not found, copying {:?}", s); Cow::Owned(s.to_owned()) } @@ -397,7 +398,7 @@ impl Headers { pub fn set(&mut self, value: H) { trace!("Headers.set( {:?}, {:?} )", header_name::(), HeaderValueString(&value)); self.data.insert(HeaderName(Ascii::new(Cow::Borrowed(header_name::()))), - Item::new_typed(Box::new(value))); + Item::new_typed(value)); } /// Get a reference to the header field's value, if it exists. @@ -682,10 +683,11 @@ impl AsRef for HeaderName { } impl PartialEq for HeaderName { + #[inline] fn eq(&self, other: &HeaderName) -> bool { let s = self.as_ref(); let k = other.as_ref(); - if s.len() == k.len() && s.as_ptr() == k.as_ptr() { + if s.as_ptr() == k.as_ptr() && s.len() == k.len() { true } else { self.0 == other.0 @@ -696,7 +698,7 @@ impl PartialEq for HeaderName { impl PartialEq for str { fn eq(&self, other: &HeaderName) -> bool { let k = other.as_ref(); - if self.len() == k.len() && self.as_ptr() == k.as_ptr() { + if self.as_ptr() == k.as_ptr() && self.len() == k.len() { true } else { other.0 == self @@ -975,6 +977,16 @@ mod tests { b.iter(|| assert!(headers.get::().is_none())) } + #[cfg(feature = "nightly")] + #[bench] + fn bench_headers_get_miss_previous_10(b: &mut Bencher) { + let mut headers = Headers::new(); + for i in 0..10 { + headers.set_raw(format!("non-standard-{}", i), "hi"); + } + b.iter(|| assert!(headers.get::().is_none())) + } + #[cfg(feature = "nightly")] #[bench] fn bench_headers_set(b: &mut Bencher) { @@ -982,6 +994,33 @@ mod tests { b.iter(|| headers.set(ContentLength(12))) } + #[cfg(feature = "nightly")] + #[bench] + fn bench_headers_set_previous_10(b: &mut Bencher) { + let mut headers = Headers::new(); + for i in 0..10 { + headers.set_raw(format!("non-standard-{}", i), "hi"); + } + b.iter(|| headers.set(ContentLength(12))) + } + + #[cfg(feature = "nightly")] + #[bench] + fn bench_headers_set_raw(b: &mut Bencher) { + let mut headers = Headers::new(); + b.iter(|| headers.set_raw("non-standard", "hello")) + } + + #[cfg(feature = "nightly")] + #[bench] + fn bench_headers_set_raw_previous_10(b: &mut Bencher) { + let mut headers = Headers::new(); + for i in 0..10 { + headers.set_raw(format!("non-standard-{}", i), "hi"); + } + b.iter(|| headers.set_raw("non-standard", "hello")) + } + #[cfg(feature = "nightly")] #[bench] fn bench_headers_has(b: &mut Bencher) { @@ -1003,8 +1042,16 @@ mod tests { #[cfg(feature = "nightly")] #[bench] fn bench_headers_fmt(b: &mut Bencher) { + use std::fmt::Write; + let mut buf = String::with_capacity(64); let mut headers = Headers::new(); headers.set(ContentLength(11)); - b.iter(|| headers.to_string()) + headers.set(ContentType::json()); + b.bytes = headers.to_string().len() as u64; + b.iter(|| { + let _ = write!(buf, "{}", headers); + ::test::black_box(&buf); + unsafe { buf.as_mut_vec().set_len(0); } + }) } }