Bug 1602458 - Prevent recycled hash maps from growing indefinitely. r=gw
authorNicolas Silva <nsilva@mozilla.com>
Thu, 12 Dec 2019 09:10:20 +0000
changeset 506641 98758fb9121864772ba6103e1562fccc1f49aefb
parent 506640 a78ae24f8d3661f4dd0a831236dbe5baed672dc8
child 506642 66e43a1f1b9f807f22d162ce01f67c0274341585
push id36910
push usercsabou@mozilla.com
push dateThu, 12 Dec 2019 21:50:40 +0000
treeherdermozilla-central@0f6958f49842 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgw
bugs1602458
milestone73.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1602458 - Prevent recycled hash maps from growing indefinitely. r=gw Differential Revision: https://phabricator.services.mozilla.com/D56560
gfx/wr/webrender/src/picture.rs
--- a/gfx/wr/webrender/src/picture.rs
+++ b/gfx/wr/webrender/src/picture.rs
@@ -1675,26 +1675,44 @@ impl TileCacheInstance {
         if let Some(prev_state) = frame_state.retained_tiles.caches.remove(&self.slice) {
             self.tiles.extend(prev_state.tiles);
             self.root_transform = prev_state.root_transform;
             self.spatial_nodes = prev_state.spatial_nodes;
             self.opacity_bindings = prev_state.opacity_bindings;
             self.current_tile_size = prev_state.current_tile_size;
 
             fn recycle_map<K: std::cmp::Eq + std::hash::Hash, V>(
+                ideal_len: usize,
                 dest: &mut FastHashMap<K, V>,
                 src: FastHashMap<K, V>,
             ) {
                 if dest.capacity() < src.capacity() {
-                    *dest = src;
+                    if src.capacity() < 3 * ideal_len {
+                        *dest = src;
+                    } else {
+                        dest.clear();
+                        dest.reserve(ideal_len);
+                    }
                 }
             }
-            recycle_map(&mut self.old_tiles, prev_state.allocations.old_tiles);
-            recycle_map(&mut self.old_opacity_bindings, prev_state.allocations.old_opacity_bindings);
-            recycle_map(&mut self.compare_cache, prev_state.allocations.compare_cache);
+            recycle_map(
+                self.tiles.len(),
+                &mut self.old_tiles,
+                prev_state.allocations.old_tiles,
+            );
+            recycle_map(
+                self.opacity_bindings.len(),
+                &mut self.old_opacity_bindings,
+                prev_state.allocations.old_opacity_bindings,
+            );
+            recycle_map(
+                prev_state.allocations.compare_cache.len(),
+                &mut self.compare_cache,
+                prev_state.allocations.compare_cache,
+            );
         }
 
         // Only evaluate what tile size to use fairly infrequently, so that we don't end
         // up constantly invalidating and reallocating tiles if the picture rect size is
         // changing near a threshold value.
         if self.frames_until_size_eval == 0 {
             const TILE_SIZE_TINY: f32 = 32.0;