From 13bfa65a8144aac591e3e6ad1c964f352af132ae Mon Sep 17 00:00:00 2001 From: Alexis Beingessner Date: Tue, 10 Oct 2017 11:17:52 -0400 Subject: [PATCH] Optimize skip_slice by recording serialized length --- webrender_api/src/display_list.rs | 37 +++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/webrender_api/src/display_list.rs b/webrender_api/src/display_list.rs index 5a1c5b6520..aa925c57d4 100644 --- a/webrender_api/src/display_list.rs +++ b/webrender_api/src/display_list.rs @@ -152,23 +152,25 @@ fn skip_slice Deserialize<'de>>( data: &mut &[u8], ) -> (ItemRange, usize) { let base = list.data.as_ptr() as usize; + + let byte_size: usize = bincode::deserialize_from(data, bincode::Infinite) + .expect("MEH: malicious input?"); let start = data.as_ptr() as usize; + let item_count: usize = bincode::deserialize_from(data, bincode::Infinite) + .expect("MEH: malicious input?"); - // Read through the values (this is a bit of a hack to reuse logic) - let mut iter = AuxIter::::new(*data); - let count = iter.len(); - for _ in &mut iter {} - let end = iter.data.as_ptr() as usize; + // Remember how many bytes item_count occupied + let item_count_size = data.as_ptr() as usize - start; let range = ItemRange { - start: start - base, - length: end - start, + start: start - base, // byte offset to item_count + length: byte_size + item_count_size, // number of bytes for item_count + payload _boo: PhantomData, }; // Adjust data pointer to skip read values - *data = &data[range.length ..]; - (range, count) + *data = &data[byte_size ..]; + (range, item_count) } impl<'a> BuiltDisplayListIter<'a> { @@ -652,12 +654,29 @@ impl DisplayListBuilder { let len = iter.len(); let mut count = 0; + // Format: + // payload_byte_size: usize, item_count: usize, [I; item_count] + + // We write a dummy value so there's room for later + let byte_size_offset = self.data.len(); + serialize_fast(&mut self.data, &0usize); serialize_fast(&mut self.data, &len); + let payload_offset = self.data.len(); + for elem in iter { count += 1; serialize_fast(&mut self.data, &elem); } + // Now write the actual byte_size + let final_offset = self.data.len(); + let byte_size = final_offset - payload_offset; + + // Note we don't use serialize_fast because we don't want to change the Vec's len + bincode::serialize_into(&mut &mut self.data[byte_size_offset..], + &byte_size, + bincode::Infinite).unwrap(); + debug_assert_eq!(len, count); }