about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-12-02 11:14:14 +0000
committerbors <bors@rust-lang.org>2018-12-02 11:14:14 +0000
commit9abc2312124de7c4275d76e9cbc81d50086c4768 (patch)
tree78b81359a2d7a8805cb5b846e1a6918b7bf28671
parent0765eb95b5e9e15fc29aa7725a01621dfeca2649 (diff)
parent95f32f1ebddae26ac6610040ea93ea3de440089a (diff)
downloadrust-9abc2312124de7c4275d76e9cbc81d50086c4768.tar.gz
rust-9abc2312124de7c4275d76e9cbc81d50086c4768.zip
Auto merge of #56378 - ljedrz:arena_tweaks, r=nagisa
arena: speed up TypedArena::clear and improve common patterns

- speed up `TypedArena::clear`: improves its performance by up to **33%** (in case of a single entry)
- simplify `DroplessArena::in_arena`
-rw-r--r--src/libarena/lib.rs24
1 files changed, 14 insertions, 10 deletions
diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs
index 955cab1d93f..aef3edd9eb6 100644
--- a/src/libarena/lib.rs
+++ b/src/libarena/lib.rs
@@ -224,14 +224,14 @@ impl<T> TypedArena<T> {
         unsafe {
             // Clear the last chunk, which is partially filled.
             let mut chunks_borrow = self.chunks.borrow_mut();
-            if let Some(mut last_chunk) = chunks_borrow.pop() {
+            if let Some(mut last_chunk) = chunks_borrow.last_mut() {
                 self.clear_last_chunk(&mut last_chunk);
+                let len = chunks_borrow.len();
                 // If `T` is ZST, code below has no effect.
-                for mut chunk in chunks_borrow.drain(..) {
+                for mut chunk in chunks_borrow.drain(..len-1) {
                     let cap = chunk.storage.cap();
                     chunk.destroy(cap);
                 }
-                chunks_borrow.push(last_chunk);
             }
         }
     }
@@ -311,13 +311,8 @@ impl Default for DroplessArena {
 impl DroplessArena {
     pub fn in_arena<T: ?Sized>(&self, ptr: *const T) -> bool {
         let ptr = ptr as *const u8 as *mut u8;
-        for chunk in &*self.chunks.borrow() {
-            if chunk.start() <= ptr && ptr < chunk.end() {
-                return true;
-            }
-        }
 
-        false
+        self.chunks.borrow().iter().any(|chunk| chunk.start() <= ptr && ptr < chunk.end())
     }
 
     #[inline]
@@ -410,7 +405,7 @@ impl DroplessArena {
     {
         assert!(!mem::needs_drop::<T>());
         assert!(mem::size_of::<T>() != 0);
-        assert!(slice.len() != 0);
+        assert!(!slice.is_empty());
 
         let mem = self.alloc_raw(
             slice.len() * mem::size_of::<T>(),
@@ -606,6 +601,15 @@ mod tests {
         }
     }
 
+    #[bench]
+    pub fn bench_typed_arena_clear(b: &mut Bencher) {
+        let mut arena = TypedArena::default();
+        b.iter(|| {
+            arena.alloc(Point { x: 1, y: 2, z: 3 });
+            arena.clear();
+        })
+    }
+
     // Drop tests
 
     struct DropCounter<'a> {