|
27 | 27 | //! value associated with a given key is removed from a slab, that key may be |
28 | 28 | //! returned from future calls to `insert`. |
29 | 29 | //! |
| 30 | +//! # Performance notes |
| 31 | +//! |
| 32 | +//! Methods that remove values and return them, such as [`Slab::remove`] and |
| 33 | +//! [`Slab::try_remove`], might copy the removed values to the stack even if |
| 34 | +//! their return values are unused. For types that don't have drop glue, the |
| 35 | +//! compiler can usually elide these copies. |
| 36 | +//! |
30 | 37 | //! # Examples |
31 | 38 | //! |
32 | 39 | //! Basic storing and retrieval. |
@@ -1115,19 +1122,21 @@ impl<T> Slab<T> { |
1115 | 1122 | /// ``` |
1116 | 1123 | pub fn try_remove(&mut self, key: usize) -> Option<T> { |
1117 | 1124 | if let Some(entry) = self.entries.get_mut(key) { |
1118 | | - // Swap the entry at the provided value |
1119 | | - let prev = mem::replace(entry, Entry::Vacant(self.next)); |
1120 | | - |
1121 | | - match prev { |
1122 | | - Entry::Occupied(val) => { |
1123 | | - self.len -= 1; |
1124 | | - self.next = key; |
1125 | | - return val.into(); |
1126 | | - } |
1127 | | - _ => { |
1128 | | - // Woops, the entry is actually vacant, restore the state |
1129 | | - *entry = prev; |
1130 | | - } |
| 1125 | + if let Entry::Occupied(_) = entry { |
| 1126 | + // Here we use `std::mem::replace` to move the entry's value to |
| 1127 | + // the stack and set the entry as vacant in one shot. By doing |
| 1128 | + // this only when the entry is occupied, the compiler should be |
| 1129 | + // able to elide copying the bytes to the stack if the value |
| 1130 | + // turns out to be unused. |
| 1131 | + |
| 1132 | + let val = match core::mem::replace(entry, Entry::Vacant(self.next)) { |
| 1133 | + Entry::Occupied(val) => val, // confirmed occupied above |
| 1134 | + _ => unreachable!(), |
| 1135 | + }; |
| 1136 | + |
| 1137 | + self.len -= 1; |
| 1138 | + self.next = key; |
| 1139 | + return val.into(); |
1131 | 1140 | } |
1132 | 1141 | } |
1133 | 1142 | None |
|
0 commit comments