-
Notifications
You must be signed in to change notification settings - Fork 102
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Refactor benchmarks: - Abstract tree creation behind a trait - Implement trait for Yoga and Taffy * Remove unused random_style module * Set super deep benchmarks back to branching factor of 1 * Feature flag small and large benchmarks * Split benchmark definitions into functions * Add deep(auto) benchmarks * Improve super-deep hierarchy benchmarks
- Loading branch information
Showing
8 changed files
with
446 additions
and
237 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,127 @@ | ||
// As each benchmark suite is compiled as a seperate crate and uses different helpers, we end up with a bunch | ||
// of false positives for this lint. So let's just disable it for this code. | ||
#![allow(dead_code)] | ||
|
||
pub mod taffy_helpers; | ||
pub use taffy_helpers::TaffyTreeBuilder; | ||
|
||
#[cfg(feature = "yoga")] | ||
pub mod yoga_helpers; | ||
#[cfg(feature = "yoga")] | ||
pub use yoga_helpers::YogaTreeBuilder; | ||
|
||
use rand::distributions::uniform::SampleRange; | ||
use rand::{Rng, SeedableRng}; | ||
use rand_chacha::ChaCha8Rng; | ||
use taffy::style::Style as TaffyStyle; | ||
|
||
pub const STANDARD_RNG_SEED: u64 = 12345; | ||
|
||
pub trait GenStyle<Style: Default> { | ||
fn create_leaf_style(&mut self, rng: &mut impl Rng) -> Style; | ||
fn create_container_style(&mut self, rng: &mut impl Rng) -> Style; | ||
fn create_root_style(&mut self, _rng: &mut impl Rng) -> Style { | ||
Default::default() | ||
} | ||
} | ||
|
||
pub struct FixedStyleGenerator(pub TaffyStyle); | ||
impl GenStyle<TaffyStyle> for FixedStyleGenerator { | ||
fn create_leaf_style(&mut self, _rng: &mut impl Rng) -> TaffyStyle { | ||
self.0.clone() | ||
} | ||
fn create_container_style(&mut self, _rng: &mut impl Rng) -> TaffyStyle { | ||
self.0.clone() | ||
} | ||
} | ||
|
||
pub trait BuildTree<R: Rng, G: GenStyle<TaffyStyle>>: Sized { | ||
type Tree; | ||
type Node: Clone; | ||
|
||
fn with_rng(rng: R, style_generator: G) -> Self; | ||
|
||
fn random_usize(&mut self, range: impl SampleRange<usize>) -> usize; | ||
fn create_leaf_node(&mut self) -> Self::Node; | ||
fn create_container_node(&mut self, children: &[Self::Node]) -> Self::Node; | ||
fn set_root_children(&mut self, children: &[Self::Node]); | ||
fn total_node_count(&mut self) -> usize; | ||
fn into_tree_and_root(self) -> (Self::Tree, Self::Node); | ||
|
||
fn build_n_leaf_nodes(&mut self, n: usize) -> Vec<Self::Node> { | ||
(0..n).map(|_| self.create_leaf_node()).collect() | ||
} | ||
|
||
mod random_style; | ||
pub use random_style::Randomizeable; | ||
|
||
/// A helper function to recursively construct a deep tree | ||
#[allow(dead_code)] | ||
pub fn build_deep_tree<T, N>( | ||
tree: &mut T, | ||
max_nodes: u32, | ||
branching_factor: u32, | ||
create_leaf_node: &mut impl FnMut(&mut T) -> N, | ||
create_container_node: &mut impl FnMut(&mut T, Vec<N>) -> N, | ||
) -> Vec<N> { | ||
if max_nodes <= branching_factor { | ||
// Build leaf nodes | ||
return (0..max_nodes).map(|_| create_leaf_node(tree)).collect(); | ||
} | ||
|
||
// Add another layer to the tree | ||
// Each child gets an equal amount of the remaining nodes | ||
(0..branching_factor) | ||
.map(|_| { | ||
let max_nodes = (max_nodes - branching_factor) / branching_factor; | ||
let sub_children = | ||
build_deep_tree(tree, max_nodes, branching_factor, create_leaf_node, create_container_node); | ||
create_container_node(tree, sub_children) | ||
}) | ||
.collect() | ||
/// A helper function to recursively construct a deep tree | ||
fn build_deep_tree(&mut self, max_nodes: u32, branching_factor: u32) -> Vec<Self::Node> { | ||
if max_nodes <= branching_factor { | ||
// Build leaf nodes | ||
return (0..max_nodes).map(|_| self.create_leaf_node()).collect(); | ||
} | ||
|
||
// Add another layer to the tree | ||
// Each child gets an equal amount of the remaining nodes | ||
(0..branching_factor) | ||
.map(|_| { | ||
let max_nodes = (max_nodes - branching_factor) / branching_factor; | ||
let children = self.build_deep_tree(max_nodes, branching_factor); | ||
self.create_container_node(&children) | ||
}) | ||
.collect() | ||
} | ||
|
||
/// A helper function to recursively construct a deep tree | ||
fn build_super_deep_hierarchy(mut self, depth: u32, nodes_per_level: u32) -> (Self::Tree, Self::Node) { | ||
let mut children = Vec::with_capacity(nodes_per_level as usize); | ||
for _ in 0..depth { | ||
let node_with_children = self.create_container_node(&children); | ||
|
||
children.clear(); | ||
children.push(node_with_children); | ||
for _ in 0..(nodes_per_level - 1) { | ||
children.push(self.create_leaf_node()) | ||
} | ||
} | ||
self.set_root_children(&children); | ||
self.into_tree_and_root() | ||
} | ||
|
||
/// A tree with a higher depth for a more realistic scenario | ||
fn build_deep_hierarchy(mut self, node_count: u32, branching_factor: u32) -> (Self::Tree, Self::Node) { | ||
let children = self.build_deep_tree(node_count, branching_factor); | ||
self.set_root_children(&children); | ||
self.into_tree_and_root() | ||
} | ||
|
||
/// A tree with many children that have shallow depth | ||
fn build_flat_hierarchy(mut self, target_node_count: u32) -> (Self::Tree, Self::Node) { | ||
let mut children = Vec::new(); | ||
|
||
while self.total_node_count() < target_node_count as usize { | ||
let count = self.random_usize(1..=4); | ||
let sub_children = self.build_n_leaf_nodes(count); | ||
let node = self.create_container_node(&sub_children); | ||
children.push(node); | ||
} | ||
|
||
self.set_root_children(&children); | ||
self.into_tree_and_root() | ||
} | ||
} | ||
|
||
pub trait BuildTreeExt<G: GenStyle<TaffyStyle>>: BuildTree<ChaCha8Rng, G> { | ||
fn with_seed(seed: u64, style_generator: G) -> Self | ||
where | ||
Self: Sized, | ||
{ | ||
let rng = ChaCha8Rng::seed_from_u64(seed); | ||
Self::with_rng(rng, style_generator) | ||
} | ||
|
||
fn new(style_generator: G) -> Self | ||
where | ||
Self: Sized, | ||
{ | ||
Self::with_seed(STANDARD_RNG_SEED, style_generator) | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
use rand::distributions::uniform::SampleRange; | ||
use rand::Rng; | ||
use rand_chacha::ChaCha8Rng; | ||
use taffy::style::Style as TaffyStyle; | ||
use taffy::tree::NodeId as TaffyNodeId; | ||
use taffy::Taffy as TaffyTree; | ||
|
||
use super::{BuildTree, BuildTreeExt, GenStyle}; | ||
|
||
pub struct TaffyTreeBuilder<R: Rng, G: GenStyle<TaffyStyle>> { | ||
rng: R, | ||
style_generator: G, | ||
tree: TaffyTree, | ||
root: TaffyNodeId, | ||
} | ||
|
||
// Implement the BuildTree trait | ||
impl<R: Rng, G: GenStyle<TaffyStyle>> BuildTree<R, G> for TaffyTreeBuilder<R, G> { | ||
type Tree = TaffyTree; | ||
type Node = TaffyNodeId; | ||
|
||
fn with_rng(mut rng: R, mut style_generator: G) -> Self { | ||
let mut tree = TaffyTree::new(); | ||
let root = tree.new_leaf(style_generator.create_root_style(&mut rng)).unwrap(); | ||
TaffyTreeBuilder { rng, style_generator, tree, root } | ||
} | ||
|
||
fn random_usize(&mut self, range: impl SampleRange<usize>) -> usize { | ||
self.rng.gen_range(range) | ||
} | ||
|
||
fn create_leaf_node(&mut self) -> Self::Node { | ||
let style = self.style_generator.create_leaf_style(&mut self.rng); | ||
self.tree.new_leaf(style).unwrap() | ||
} | ||
|
||
fn create_container_node(&mut self, children: &[Self::Node]) -> Self::Node { | ||
let style = self.style_generator.create_container_style(&mut self.rng); | ||
self.tree.new_with_children(style, children).unwrap() | ||
} | ||
|
||
fn total_node_count(&mut self) -> usize { | ||
self.tree.total_node_count() | ||
} | ||
|
||
fn set_root_children(&mut self, children: &[Self::Node]) { | ||
self.tree.set_children(self.root, children).unwrap(); | ||
} | ||
|
||
fn into_tree_and_root(self) -> (Self::Tree, Self::Node) { | ||
(self.tree, self.root) | ||
} | ||
} | ||
|
||
impl<G: GenStyle<TaffyStyle>> BuildTreeExt<G> for TaffyTreeBuilder<ChaCha8Rng, G> {} |
Oops, something went wrong.