diff options
| author | Nicholas Nethercote <nnethercote@mozilla.com> | 2016-10-10 09:07:18 +1100 |
|---|---|---|
| committer | Nicholas Nethercote <nnethercote@mozilla.com> | 2016-10-10 10:36:35 +1100 |
| commit | b043e11de2eb2c60f7bfec5e15960f537b229e20 (patch) | |
| tree | 575489dfffc417cc045cb370a35672cd424e6b1f /src/libserialize | |
| parent | 9d4d0da7af77858f268a66ff144134945c880560 (diff) | |
| download | rust-b043e11de2eb2c60f7bfec5e15960f537b229e20.tar.gz rust-b043e11de2eb2c60f7bfec5e15960f537b229e20.zip | |
Avoid allocations in `Decoder::read_str`.
`opaque::Decoder::read_str` is very hot within `rustc` due to its use in the reading of crate metadata, and it currently returns a `String`. This commit changes it to instead return a `Cow<str>`, which avoids a heap allocation. This change reduces the number of calls to `malloc` by almost 10% in some benchmarks. This is a [breaking-change] to libserialize.
Diffstat (limited to 'src/libserialize')
| -rw-r--r-- | src/libserialize/json.rs | 7 | ||||
| -rw-r--r-- | src/libserialize/opaque.rs | 5 | ||||
| -rw-r--r-- | src/libserialize/serialize.rs | 5 |
3 files changed, 9 insertions, 8 deletions
diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 5e25c61bae9..3e976c90628 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -199,6 +199,7 @@ use self::DecoderError::*; use self::ParserState::*; use self::InternalStackElement::*; +use std::borrow::Cow; use std::collections::{HashMap, BTreeMap}; use std::io::prelude::*; use std::io; @@ -2081,9 +2082,7 @@ impl Decoder { pub fn new(json: Json) -> Decoder { Decoder { stack: vec![json] } } -} -impl Decoder { fn pop(&mut self) -> Json { self.stack.pop().unwrap() } @@ -2182,8 +2181,8 @@ impl ::Decoder for Decoder { Err(ExpectedError("single character string".to_owned(), format!("{}", s))) } - fn read_str(&mut self) -> DecodeResult<string::String> { - expect!(self.pop(), String) + fn read_str(&mut self) -> DecodeResult<Cow<str>> { + expect!(self.pop(), String).map(Cow::Owned) } fn read_enum<T, F>(&mut self, _name: &str, f: F) -> DecodeResult<T> where diff --git a/src/libserialize/opaque.rs b/src/libserialize/opaque.rs index e97834f63ce..a2c0ca95447 100644 --- a/src/libserialize/opaque.rs +++ b/src/libserialize/opaque.rs @@ -9,6 +9,7 @@ // except according to those terms. use leb128::{read_signed_leb128, read_unsigned_leb128, write_signed_leb128, write_unsigned_leb128}; +use std::borrow::Cow; use std::io::{self, Write}; use serialize; @@ -246,11 +247,11 @@ impl<'a> serialize::Decoder for Decoder<'a> { Ok(::std::char::from_u32(bits).unwrap()) } - fn read_str(&mut self) -> Result<String, Self::Error> { + fn read_str(&mut self) -> Result<Cow<str>, Self::Error> { let len = self.read_usize()?; let s = ::std::str::from_utf8(&self.data[self.position..self.position + len]).unwrap(); self.position += len; - Ok(s.to_string()) + Ok(Cow::Borrowed(s)) } fn error(&mut self, err: &str) -> Self::Error { diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index 6650a981884..c4613c661a8 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -14,6 +14,7 @@ Core encoding and decoding interfaces. */ +use std::borrow::Cow; use std::intrinsics; use std::path; use std::rc::Rc; @@ -156,7 +157,7 @@ pub trait Decoder { fn read_f64(&mut self) -> Result<f64, Self::Error>; fn read_f32(&mut self) -> Result<f32, Self::Error>; fn read_char(&mut self) -> Result<char, Self::Error>; - fn read_str(&mut self) -> Result<String, Self::Error>; + fn read_str(&mut self) -> Result<Cow<str>, Self::Error>; // Compound types: fn read_enum<T, F>(&mut self, _name: &str, f: F) -> Result<T, Self::Error> @@ -401,7 +402,7 @@ impl Encodable for String { impl Decodable for String { fn decode<D: Decoder>(d: &mut D) -> Result<String, D::Error> { - d.read_str() + Ok(d.read_str()?.into_owned()) } } |
