about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-01-26 13:01:00 +0000
committerbors <bors@rust-lang.org>2015-01-26 13:01:00 +0000
commit977c44ade09450016d9c95dea245fd4464a509e9 (patch)
treeadea995c7831ebae76bca46e243cbd124f53626b /src
parent59dcba5d14e5eada0a5e7eb0cad5efc7acd1d0e3 (diff)
parentc384ee18fcb55274682e8a9a24608bfc825bedce (diff)
downloadrust-977c44ade09450016d9c95dea245fd4464a509e9.tar.gz
rust-977c44ade09450016d9c95dea245fd4464a509e9.zip
Auto merge of #21401 - kballard:optimize-shrink-to-fit, r=nikomatsakis
Don't reallocate when capacity is already equal to length

`Vec::shrink_to_fit()` may be called on vectors that are already the
correct length. Calling out to `reallocate()` in this case is a bad idea
because there is no guarantee that `reallocate()` won't allocate a new
buffer anyway, and based on performance seen in external benchmarks, it
seems likely that it is in fact reallocating a new buffer.

Before:

    test string::tests::bench_exact_size_shrink_to_fit         ... bench:        45 ns/iter (+/- 2)

After:

    test string::tests::bench_exact_size_shrink_to_fit         ... bench:        26 ns/iter (+/- 1)
Diffstat (limited to 'src')
-rw-r--r--src/libcollections/string.rs16
-rw-r--r--src/libcollections/vec.rs2
2 files changed, 17 insertions, 1 deletions
diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs
index c965aedbc5d..562189370d6 100644
--- a/src/libcollections/string.rs
+++ b/src/libcollections/string.rs
@@ -1413,4 +1413,20 @@ mod tests {
             let _ = String::from_utf8_lossy(s.as_slice());
         });
     }
+
+    #[bench]
+    fn bench_exact_size_shrink_to_fit(b: &mut Bencher) {
+        let s = "Hello there, the quick brown fox jumped over the lazy dog! \
+                 Lorem ipsum dolor sit amet, consectetur. ";
+        // ensure our operation produces an exact-size string before we benchmark it
+        let mut r = String::with_capacity(s.len());
+        r.push_str(s);
+        assert_eq!(r.len(), r.capacity());
+        b.iter(|| {
+            let mut r = String::with_capacity(s.len());
+            r.push_str(s);
+            r.shrink_to_fit();
+            r
+        });
+    }
 }
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index 52590297a6a..0de9b5733fb 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -356,7 +356,7 @@ impl<T> Vec<T> {
                 }
                 self.cap = 0;
             }
-        } else {
+        } else if self.cap != self.len {
             unsafe {
                 // Overflow check is unnecessary as the vector is already at
                 // least this large.