Bug 1602458 - Avoid unnecessary vector allocations when splitting the tile cache. r=gw
authorNicolas Silva <nsilva@mozilla.com>
Thu, 12 Dec 2019 09:15:02 +0000
changeset 506639 1f03147b38545bffc24dcccd819114922860b30e
parent 506638 59cfb8104165cd5d25ab10abe0b634995b6a9552
child 506640 a78ae24f8d3661f4dd0a831236dbe5baed672dc8
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 - Avoid unnecessary vector allocations when splitting the tile cache. r=gw Differential Revision: https://phabricator.services.mozilla.com/D56417
gfx/wr/webrender/src/picture.rs
--- a/gfx/wr/webrender/src/picture.rs
+++ b/gfx/wr/webrender/src/picture.rs
@@ -4843,38 +4843,39 @@ impl TileNode {
                 }
             }
         }
     }
 
     /// Calculate the four child rects for a given node
     fn get_child_rects(
         rect: &PictureRect,
-    ) -> Vec<PictureRect> {
+        result: &mut [PictureRect; 4],
+    ) {
         let p0 = rect.origin;
         let half_size = PictureSize::new(rect.size.width * 0.5, rect.size.height * 0.5);
 
-        [
+        *result = [
             PictureRect::new(
                 PicturePoint::new(p0.x, p0.y),
                 half_size,
             ),
             PictureRect::new(
                 PicturePoint::new(p0.x + half_size.width, p0.y),
                 half_size,
             ),
             PictureRect::new(
                 PicturePoint::new(p0.x, p0.y + half_size.height),
                 half_size,
             ),
             PictureRect::new(
                 PicturePoint::new(p0.x + half_size.width, p0.y + half_size.height),
                 half_size,
             ),
-        ].to_vec()
+        ];
     }
 
     /// Called during pre_update, to clear the current dependencies
     fn clear(
         &mut self,
         rect: PictureRect,
     ) {
         self.rect = rect;
@@ -4884,17 +4885,18 @@ impl TileNode {
                 // Swap current dependencies to be the previous frame
                 mem::swap(prev_indices, curr_indices);
                 curr_indices.clear();
                 // Note that another frame has passed in the dirty bit trackers
                 *dirty_tracker = *dirty_tracker << 1;
                 *frames_since_modified += 1;
             }
             TileNodeKind::Node { ref mut children, .. } => {
-                let child_rects = TileNode::get_child_rects(&rect);
+                let mut child_rects = [PictureRect::zero(); 4];
+                TileNode::get_child_rects(&rect, &mut child_rects);
                 assert_eq!(child_rects.len(), children.len());
 
                 for (child, rect) in children.iter_mut().zip(child_rects.iter()) {
                     child.clear(*rect);
                 }
             }
         }
     }
@@ -4996,35 +4998,43 @@ impl TileNode {
                     TileNodeKind::Node { .. } => {
                         unreachable!("bug - only leaves can split");
                     }
                     TileNodeKind::Leaf { ref mut curr_indices, .. } => {
                         curr_indices.take()
                     }
                 };
 
-                // TODO(gw): We know that these are fixed arrays, we could do better with
-                //           allocations here!
-                let child_rects = TileNode::get_child_rects(&self.rect);
-                let child_rects: Vec<RectangleKey> = child_rects.iter().map(|r| (*r).into()).collect();
-                let mut child_indices = vec![Vec::new(); child_rects.len()];
+                let mut child_rects = [PictureRect::zero(); 4];
+                TileNode::get_child_rects(&self.rect, &mut child_rects);
+
+                let mut child_indices = [
+                    Vec::new(),
+                    Vec::new(),
+                    Vec::new(),
+                    Vec::new(),
+                ];
 
                 // Step through the index buffer, and add primitives to each of the children
                 // that they intersect.
                 for index in curr_indices {
                     let prim = &curr_prims[index.0 as usize];
                     for (child_rect, indices) in child_rects.iter().zip(child_indices.iter_mut()) {
-                        if prim.prim_clip_rect.intersects(child_rect) {
+                        let child_rect_key: RectangleKey = (*child_rect).into();
+                        if prim.prim_clip_rect.intersects(&child_rect_key) {
                             indices.push(index);
                         }
                     }
                 }
 
                 // Create the child nodes and switch from leaf -> node.
-                let children = child_indices.into_iter().map(|i| TileNode::new_leaf(i)).collect();
+                let children = child_indices
+                    .iter_mut()
+                    .map(|i| TileNode::new_leaf(mem::replace(i, Vec::new())))
+                    .collect();
 
                 self.kind = TileNodeKind::Node {
                     children: children,
                 };
             }
             Some(TileModification::Merge) => {
                 // Construct a merged index buffer by collecting the dependency index buffers
                 // from each child, and merging them into a de-duplicated index buffer.