perf(header): optimize when inserting a new type header
This commit is contained in:
		| @@ -58,6 +58,11 @@ impl<V: ?Sized + Any + 'static> PtrMapCell<V> { | |||||||
|         PtrMapCell(UnsafeCell::new(PtrMap::Empty)) |         PtrMapCell(UnsafeCell::new(PtrMap::Empty)) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     #[inline] | ||||||
|  |     pub fn with_one(key: TypeId, val: Box<V>)  -> PtrMapCell<V> { | ||||||
|  |         PtrMapCell(UnsafeCell::new(PtrMap::One(key, val))) | ||||||
|  |     } | ||||||
|  |  | ||||||
|     #[inline] |     #[inline] | ||||||
|     pub fn get(&self, key: TypeId) -> Option<&V> { |     pub fn get(&self, key: TypeId) -> Option<&V> { | ||||||
|         let map = unsafe { &*self.0.get() }; |         let map = unsafe { &*self.0.get() }; | ||||||
|   | |||||||
| @@ -23,12 +23,11 @@ impl Item { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     #[inline] |     #[inline] | ||||||
|     pub fn new_typed(ty: Box<Header + Send + Sync>) -> Item { |  | ||||||
|         let map = PtrMapCell::new(); |     pub fn new_typed<H: Header>(val: H) -> Item { | ||||||
|         unsafe { map.insert((*ty).get_type(), ty); } |  | ||||||
|         Item { |         Item { | ||||||
|             raw: OptCell::new(None), |             raw: OptCell::new(None), | ||||||
|             typed: map, |             typed: PtrMapCell::with_one(TypeId::of::<H>(), Box::new(val)), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -344,6 +344,7 @@ macro_rules! literals { | |||||||
|                 _ => () |                 _ => () | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             trace!("maybe_literal not found, copying {:?}", s); | ||||||
|             Cow::Owned(s.to_owned()) |             Cow::Owned(s.to_owned()) | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -397,7 +398,7 @@ impl Headers { | |||||||
|     pub fn set<H: Header>(&mut self, value: H) { |     pub fn set<H: Header>(&mut self, value: H) { | ||||||
|         trace!("Headers.set( {:?}, {:?} )", header_name::<H>(), HeaderValueString(&value)); |         trace!("Headers.set( {:?}, {:?} )", header_name::<H>(), HeaderValueString(&value)); | ||||||
|         self.data.insert(HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))), |         self.data.insert(HeaderName(Ascii::new(Cow::Borrowed(header_name::<H>()))), | ||||||
|                          Item::new_typed(Box::new(value))); |                          Item::new_typed(value)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /// Get a reference to the header field's value, if it exists. |     /// Get a reference to the header field's value, if it exists. | ||||||
| @@ -682,10 +683,11 @@ impl AsRef<str> for HeaderName { | |||||||
| } | } | ||||||
|  |  | ||||||
| impl PartialEq for HeaderName { | impl PartialEq for HeaderName { | ||||||
|  |     #[inline] | ||||||
|     fn eq(&self, other: &HeaderName) -> bool { |     fn eq(&self, other: &HeaderName) -> bool { | ||||||
|         let s = self.as_ref(); |         let s = self.as_ref(); | ||||||
|         let k = other.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 |             true | ||||||
|         } else { |         } else { | ||||||
|             self.0 == other.0 |             self.0 == other.0 | ||||||
| @@ -696,7 +698,7 @@ impl PartialEq for HeaderName { | |||||||
| impl PartialEq<HeaderName> for str { | impl PartialEq<HeaderName> for str { | ||||||
|     fn eq(&self, other: &HeaderName) -> bool { |     fn eq(&self, other: &HeaderName) -> bool { | ||||||
|         let k = other.as_ref(); |         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 |             true | ||||||
|         } else { |         } else { | ||||||
|             other.0 == self |             other.0 == self | ||||||
| @@ -975,6 +977,16 @@ mod tests { | |||||||
|         b.iter(|| assert!(headers.get::<ContentLength>().is_none())) |         b.iter(|| assert!(headers.get::<ContentLength>().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::<ContentLength>().is_none())) | ||||||
|  |     } | ||||||
|  |  | ||||||
|     #[cfg(feature = "nightly")] |     #[cfg(feature = "nightly")] | ||||||
|     #[bench] |     #[bench] | ||||||
|     fn bench_headers_set(b: &mut Bencher) { |     fn bench_headers_set(b: &mut Bencher) { | ||||||
| @@ -982,6 +994,33 @@ mod tests { | |||||||
|         b.iter(|| headers.set(ContentLength(12))) |         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")] |     #[cfg(feature = "nightly")] | ||||||
|     #[bench] |     #[bench] | ||||||
|     fn bench_headers_has(b: &mut Bencher) { |     fn bench_headers_has(b: &mut Bencher) { | ||||||
| @@ -1003,8 +1042,16 @@ mod tests { | |||||||
|     #[cfg(feature = "nightly")] |     #[cfg(feature = "nightly")] | ||||||
|     #[bench] |     #[bench] | ||||||
|     fn bench_headers_fmt(b: &mut Bencher) { |     fn bench_headers_fmt(b: &mut Bencher) { | ||||||
|  |         use std::fmt::Write; | ||||||
|  |         let mut buf = String::with_capacity(64); | ||||||
|         let mut headers = Headers::new(); |         let mut headers = Headers::new(); | ||||||
|         headers.set(ContentLength(11)); |         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); } | ||||||
|  |         }) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user