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

calculate_rows() in TextView is called multiple times per second -> bad performance #582

Closed
Builditluc opened this issue May 17, 2021 · 2 comments

Comments

@Builditluc
Copy link
Contributor

As I wrote in #578 when I display a large amount of text in a TextView the application get's slow. Since the problem this issue describes is fixed (sort of) I'm creating a new issue here . I wrote a custom view (mostly copied the TextView code) and then I found out that required_size() is called many times (40+) per second, each time with a different size parameter. Because of this calculate_rows() is called 40+ times per second which than slows down the application. Is there any way to "fix" this?

Here is a part of the log file (the window/view was idle):
image

@gyscos
Copy link
Owner

gyscos commented May 19, 2021

Hi, and thanks for the report!

The current caching strategy is a bit brittle as you noticed; requests with conflicting constraints will keep invalidating this cache, blowing up performance. LinearLayout in particular sometimes send such different requests, especially when "constrained" (it cannot give all views the size they want).

We need to improve things here - either make caching more robust, possibly adding a few "historical" cache values, or reduce the number or requests LinearLayout send its children (maybe relying itself on some better cache), or a mix of both.

@Builditluc
Copy link
Contributor Author

Builditluc commented May 19, 2021

I now added a few more caches to linear_layout::Child.

This should reduce the number fo requests LinearLayout send it's children

This is the function required_size of linear_layout::Child:

// Compute and caches the required size.
fn required_size(&mut self, req: Vec2) -> Vec2 {
    // do we already have the required size calculated and cached?
    for size in self.sizes.iter() {
        if size.is_some() {
            let req_size = size.unwrap().0;
            if req_size == req {
                return size.unwrap().1;
            }
        }
    }

    // if we don't have the size calculated, calculate it and add it to the cache
    self.required_size = self.view.required_size(req);
    // is the cache full? then remove the last element
    if self.sizes.len() == 4 {
        self.sizes.pop()
    }

    self.sizes.insert(0, Some((req, self.required_size)));
    self.required_size
}

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

2 participants