Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deep nesting results in poor performance #71

Open
AlexCharlton opened this issue Jun 14, 2020 · 2 comments
Open

Deep nesting results in poor performance #71

AlexCharlton opened this issue Jun 14, 2020 · 2 comments

Comments

@AlexCharlton
Copy link

I'm using stretch to lay out a tree-like structure. With 63 nodes and a maximum depth of 16, compute_layout takes about 5 seconds to complete. Profiling illustrates that compute time increases exponentially with depth, and that compute_internal is called over 50k times for my structure of 63 nodes.

Is this sort of performance expected? Is nesting this deeply just an entirely unexpected thing to be doing with stretch? Are there constraints I could be putting in place to elide some of this recursion?

@emilsjolander
Copy link
Contributor

This is not expected. It should scale much much better than this. Probably something to do with a specific calculation which means it's very tied to the specific tree you are passing in. Could you write a benchmark and submit it as a pull request (extending the current benchmark suite) so that we could have a look?

@mockersf
Copy link

I have met the same issue.

The following code can show it:

use std::time::SystemTime;
use stretch::geometry::Size;
use stretch::style::*;

fn main() -> Result<(), stretch::Error> {
    let mut stretch = stretch::node::Stretch::new();

    let node = stretch.new_node(
        Style { size: Size { width: Dimension::Points(50.), height: Dimension::Points(50.) }, ..Default::default() },
        vec![],
    )?;
    let mut child = stretch.new_node(Style::default(), vec![])?;
    stretch.set_children(node, vec![child]).unwrap();

    for i in 0..20 {
        let new_child = stretch.new_node(Style::default(), vec![])?;
        stretch.set_children(child, vec![new_child]).unwrap();
        child = new_child;

        let now = SystemTime::now();
        stretch.compute_layout(node, Size::undefined())?;
        println!("elapsed: {} nodes -> {:?}", i + 3, now.elapsed());
    }

    Ok(())
}

in debug mode:

elapsed: 3 nodes -> Ok(120µs)
elapsed: 4 nodes -> Ok(161µs)
elapsed: 5 nodes -> Ok(334µs)
elapsed: 6 nodes -> Ok(704µs)
elapsed: 7 nodes -> Ok(1.437ms)
elapsed: 8 nodes -> Ok(2.597ms)
elapsed: 9 nodes -> Ok(8.257ms)
elapsed: 10 nodes -> Ok(14.653ms)
elapsed: 11 nodes -> Ok(19.779ms)
elapsed: 12 nodes -> Ok(36.805ms)
elapsed: 13 nodes -> Ok(67.413ms)
elapsed: 14 nodes -> Ok(130.294ms)
elapsed: 15 nodes -> Ok(268.727ms)
elapsed: 16 nodes -> Ok(519.621ms)
elapsed: 17 nodes -> Ok(1.024435s)
elapsed: 18 nodes -> Ok(2.03991s)
elapsed: 19 nodes -> Ok(4.078674s)
elapsed: 20 nodes -> Ok(8.230985s)
elapsed: 21 nodes -> Ok(17.050925s)
elapsed: 22 nodes -> Ok(34.905185s)

and in release:

elapsed: 3 nodes -> Ok(31µs)
elapsed: 4 nodes -> Ok(15µs)
elapsed: 5 nodes -> Ok(29µs)
elapsed: 6 nodes -> Ok(64µs)
elapsed: 7 nodes -> Ok(177µs)
elapsed: 8 nodes -> Ok(260µs)
elapsed: 9 nodes -> Ok(497µs)
elapsed: 10 nodes -> Ok(836µs)
elapsed: 11 nodes -> Ok(1.696ms)
elapsed: 12 nodes -> Ok(3.272ms)
elapsed: 13 nodes -> Ok(6.373ms)
elapsed: 14 nodes -> Ok(10.881ms)
elapsed: 15 nodes -> Ok(21.904ms)
elapsed: 16 nodes -> Ok(45.07ms)
elapsed: 17 nodes -> Ok(76.651ms)
elapsed: 18 nodes -> Ok(145.677ms)
elapsed: 19 nodes -> Ok(296.503ms)
elapsed: 20 nodes -> Ok(590.395ms)
elapsed: 21 nodes -> Ok(1.150736s)
elapsed: 22 nodes -> Ok(2.323467s)

adding one node as a leaf doubles the compute_layout time

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants