about summary refs log tree commit diff
path: root/src/libstd/io
diff options
context:
space:
mode:
authorErick Tryzelaar <erick.tryzelaar@gmail.com>2014-07-29 16:31:39 -0700
committerErick Tryzelaar <erick.tryzelaar@gmail.com>2014-07-29 16:31:39 -0700
commite27b88d5bd09eb111d2936f3c6214baf1839a194 (patch)
tree58df3c76e3fcab4ed2f58ba5ad95ea8827f5cce6 /src/libstd/io
parentce2824dafe2f7b0783c2d841afe27c762528d02e (diff)
downloadrust-e27b88d5bd09eb111d2936f3c6214baf1839a194.tar.gz
rust-e27b88d5bd09eb111d2936f3c6214baf1839a194.zip
remove seek from std::io::MemWriter, add SeekableMemWriter to librustc
Not all users of MemWriter need to seek, but having MemWriter
seekable adds between 3-29% in overhead in certain circumstances.
This fixes that performance gap by making a non-seekable MemWriter,
and creating a new SeekableMemWriter for those circumstances when
that functionality is actually needed.

```
test io::mem::test::bench_buf_reader                        ... bench:       682 ns/iter (+/- 85)
test io::mem::test::bench_buf_writer                        ... bench:       580 ns/iter (+/- 57)
test io::mem::test::bench_mem_reader                        ... bench:       793 ns/iter (+/- 99)
test io::mem::test::bench_mem_writer_001_0000               ... bench:        48 ns/iter (+/- 27)
test io::mem::test::bench_mem_writer_001_0010               ... bench:        65 ns/iter (+/- 27) = 153 MB/s
test io::mem::test::bench_mem_writer_001_0100               ... bench:       132 ns/iter (+/- 12) = 757 MB/s
test io::mem::test::bench_mem_writer_001_1000               ... bench:       802 ns/iter (+/- 151) = 1246 MB/s
test io::mem::test::bench_mem_writer_100_0000               ... bench:       481 ns/iter (+/- 28)
test io::mem::test::bench_mem_writer_100_0010               ... bench:      1957 ns/iter (+/- 126) = 510 MB/s
test io::mem::test::bench_mem_writer_100_0100               ... bench:      8222 ns/iter (+/- 434) = 1216 MB/s
test io::mem::test::bench_mem_writer_100_1000               ... bench:     82496 ns/iter (+/- 11191) = 1212 MB/s
test io::mem::test::bench_seekable_mem_writer_001_0000      ... bench:        48 ns/iter (+/- 2)
test io::mem::test::bench_seekable_mem_writer_001_0010      ... bench:        64 ns/iter (+/- 2) = 156 MB/s
test io::mem::test::bench_seekable_mem_writer_001_0100      ... bench:       129 ns/iter (+/- 7) = 775 MB/s
test io::mem::test::bench_seekable_mem_writer_001_1000      ... bench:       801 ns/iter (+/- 159) = 1248 MB/s
test io::mem::test::bench_seekable_mem_writer_100_0000      ... bench:       711 ns/iter (+/- 51)
test io::mem::test::bench_seekable_mem_writer_100_0010      ... bench:      2532 ns/iter (+/- 227) = 394 MB/s
test io::mem::test::bench_seekable_mem_writer_100_0100      ... bench:      8962 ns/iter (+/- 947) = 1115 MB/s
test io::mem::test::bench_seekable_mem_writer_100_1000      ... bench:     85086 ns/iter (+/- 11555) = 1175 MB/s
```

[breaking-change]
Diffstat (limited to 'src/libstd/io')
-rw-r--r--src/libstd/io/fs.rs2
-rw-r--r--src/libstd/io/mem.rs77
2 files changed, 7 insertions, 72 deletions
diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs
index 790fe6cb8b9..f9f8ce377ec 100644
--- a/src/libstd/io/fs.rs
+++ b/src/libstd/io/fs.rs
@@ -955,7 +955,7 @@ mod test {
         }
     ) )
 
-    struct TempDir(Path);
+    pub struct TempDir(Path);
 
     impl TempDir {
         fn join(&self, path: &str) -> Path {
diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs
index b93b84b7d63..8a60233cb5c 100644
--- a/src/libstd/io/mem.rs
+++ b/src/libstd/io/mem.rs
@@ -22,6 +22,8 @@ use slice;
 use slice::{Vector, ImmutableVector, MutableVector};
 use vec::Vec;
 
+static BUF_CAPACITY: uint = 128;
+
 fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64> {
     // compute offset as signed and clamp to prevent overflow
     let pos = match seek {
@@ -56,27 +58,23 @@ fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64>
 /// ```
 pub struct MemWriter {
     buf: Vec<u8>,
-    pos: uint,
 }
 
 impl MemWriter {
     /// Create a new `MemWriter`.
     #[inline]
     pub fn new() -> MemWriter {
-        MemWriter::with_capacity(128)
+        MemWriter::with_capacity(BUF_CAPACITY)
     }
     /// Create a new `MemWriter`, allocating at least `n` bytes for
     /// the internal buffer.
     #[inline]
     pub fn with_capacity(n: uint) -> MemWriter {
-        MemWriter { buf: Vec::with_capacity(n), pos: 0 }
+        MemWriter { buf: Vec::with_capacity(n) }
     }
 
     /// Acquires an immutable reference to the underlying buffer of this
     /// `MemWriter`.
-    ///
-    /// No method is exposed for acquiring a mutable reference to the buffer
-    /// because it could corrupt the state of this `MemWriter`.
     #[inline]
     pub fn get_ref<'a>(&'a self) -> &'a [u8] { self.buf.as_slice() }
 
@@ -88,44 +86,7 @@ impl MemWriter {
 impl Writer for MemWriter {
     #[inline]
     fn write(&mut self, buf: &[u8]) -> IoResult<()> {
-        // Make sure the internal buffer is as least as big as where we
-        // currently are
-        let difference = self.pos as i64 - self.buf.len() as i64;
-        if difference > 0 {
-            self.buf.grow(difference as uint, &0);
-        }
-
-        // Figure out what bytes will be used to overwrite what's currently
-        // there (left), and what will be appended on the end (right)
-        let cap = self.buf.len() - self.pos;
-        let (left, right) = if cap <= buf.len() {
-            (buf.slice_to(cap), buf.slice_from(cap))
-        } else {
-            (buf, &[])
-        };
-
-        // Do the necessary writes
-        if left.len() > 0 {
-            slice::bytes::copy_memory(self.buf.mut_slice_from(self.pos), left);
-        }
-        if right.len() > 0 {
-            self.buf.push_all(right);
-        }
-
-        // Bump us forward
-        self.pos += buf.len();
-        Ok(())
-    }
-}
-
-impl Seek for MemWriter {
-    #[inline]
-    fn tell(&self) -> IoResult<u64> { Ok(self.pos as u64) }
-
-    #[inline]
-    fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
-        let new = try!(combine(style, self.pos, self.buf.len(), pos));
-        self.pos = new as uint;
+        self.buf.push_all(buf);
         Ok(())
     }
 }
@@ -381,30 +342,10 @@ mod test {
     #[test]
     fn test_mem_writer() {
         let mut writer = MemWriter::new();
-        assert_eq!(writer.tell(), Ok(0));
         writer.write([0]).unwrap();
-        assert_eq!(writer.tell(), Ok(1));
         writer.write([1, 2, 3]).unwrap();
         writer.write([4, 5, 6, 7]).unwrap();
-        assert_eq!(writer.tell(), Ok(8));
         assert_eq!(writer.get_ref(), &[0, 1, 2, 3, 4, 5, 6, 7]);
-
-        writer.seek(0, SeekSet).unwrap();
-        assert_eq!(writer.tell(), Ok(0));
-        writer.write([3, 4]).unwrap();
-        assert_eq!(writer.get_ref(), &[3, 4, 2, 3, 4, 5, 6, 7]);
-
-        writer.seek(1, SeekCur).unwrap();
-        writer.write([0, 1]).unwrap();
-        assert_eq!(writer.get_ref(), &[3, 4, 2, 0, 1, 5, 6, 7]);
-
-        writer.seek(-1, SeekEnd).unwrap();
-        writer.write([1, 2]).unwrap();
-        assert_eq!(writer.get_ref(), &[3, 4, 2, 0, 1, 5, 6, 1, 2]);
-
-        writer.seek(1, SeekEnd).unwrap();
-        writer.write([1]).unwrap();
-        assert_eq!(writer.get_ref(), &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1]);
     }
 
     #[test]
@@ -570,10 +511,6 @@ mod test {
         r.seek(10, SeekSet).unwrap();
         assert!(r.read(&mut []).is_err());
 
-        let mut r = MemWriter::new();
-        r.seek(10, SeekSet).unwrap();
-        assert!(r.write([3]).is_ok());
-
         let mut buf = [0];
         let mut r = BufWriter::new(buf);
         r.seek(10, SeekSet).unwrap();
@@ -589,9 +526,6 @@ mod test {
         let mut r = MemReader::new(vec!(10));
         assert!(r.seek(-1, SeekSet).is_err());
 
-        let mut r = MemWriter::new();
-        assert!(r.seek(-1, SeekSet).is_err());
-
         let mut buf = [0];
         let mut r = BufWriter::new(buf);
         assert!(r.seek(-1, SeekSet).is_err());
@@ -614,6 +548,7 @@ mod test {
     fn do_bench_mem_writer(b: &mut Bencher, times: uint, len: uint) {
         let src: Vec<u8> = Vec::from_elem(len, 5);
 
+        b.bytes = (times * len) as u64;
         b.iter(|| {
             let mut wr = MemWriter::new();
             for _ in range(0, times) {