PathBuilder: use a SmallVec while the path commands are being accumulated

From the last commit, we had this for the big SVG file in #574:

--------------------------------------------------------------------------------
  n        time(i)         total(B)   useful-heap(B) extra-heap(B)    stacks(B)
--------------------------------------------------------------------------------
 30 22,796,106,012    1,553,581,072    1,329,943,324   223,637,748            0
                                                       ^^^^^^^^^^^

That extra-heap is a lot of allocator metadata or waste space,
possibly from heap fragmentation due to all the realloc() shenanigans
from using into_boxed_slice() on the starting Vec<PathCommand>.

This commit makes PathBuilder use a SmallVec:

    pub struct PathBuilder {
        path_commands: SmallVec<[PathCommand; 32]>,
    }

That is, it will keep up to 32 PathCommand directly inside itself, and
only spill to a heap allocation if more elements come in.

We still into_boxed_slice() for the final Path.  Hopefully this makes
realloc() find heap blocks that are more closely packed.  Indeed:

--------------------------------------------------------------------------------
  n        time(i)         total(B)   useful-heap(B) extra-heap(B)    stacks(B)
--------------------------------------------------------------------------------
 33 24,139,598,653    1,416,831,176    1,329,943,212    86,887,964            0
                                                        ^^^^^^^^^^

That's a lot of less waste space.  Note also how the total bytes
shrinks from 1,553,581,072 to 1,416,831,176.
parent fc44abd1
......@@ -1366,6 +1366,7 @@ dependencies = [
"rctree 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
......
......@@ -35,6 +35,7 @@ rayon = "1"
rctree = "0.3.3"
regex = "1"
selectors = "0.22.0"
smallvec = "1.2.0"
url = "2"
xml-rs = "0.8.0"
......
//! Representation of Bézier paths.
use smallvec::SmallVec;
use std::f64;
use std::f64::consts::*;
......@@ -294,9 +296,9 @@ impl PathCommand {
///
/// When you are finished constructing a path builder, turn it into
/// a `Path` with `into_path`.
#[derive(Clone, Default)]
#[derive(Clone)]
pub struct PathBuilder {
path_commands: Vec<PathCommand>,
path_commands: SmallVec<[PathCommand; 32]>,
}
/// An immutable path
......@@ -308,7 +310,9 @@ pub struct Path {
impl PathBuilder {
pub fn new() -> PathBuilder {
PathBuilder::default()
PathBuilder {
path_commands: SmallVec::new(),
}
}
pub fn into_path(self) -> Path {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment