about summary refs log tree commit diff
path: root/src/libserialize
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2016-10-12 10:15:27 -0700
committerAlex Crichton <alex@alexcrichton.com>2016-10-12 14:07:56 -0700
commitf05bd1b41ddda779032f4c5c8e30bf640129832f (patch)
tree20136a8f6a2215e22703c51ba54c78426c3837fe /src/libserialize
parenta0ad6616fc2244eea66c6adadd35f899b170505f (diff)
parentb043e11de2eb2c60f7bfec5e15960f537b229e20 (diff)
downloadrust-f05bd1b41ddda779032f4c5c8e30bf640129832f.tar.gz
rust-f05bd1b41ddda779032f4c5c8e30bf640129832f.zip
Rollup merge of #37064 - nnethercote:read_str, r=eddyb
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.rs7
-rw-r--r--src/libserialize/opaque.rs5
-rw-r--r--src/libserialize/serialize.rs5
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())
     }
 }