gyscos / gyscos/cursive

Investigate layout cache improvement

Open
#418 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
4.8k
Forks
270
Avg merge
5d 19h
Merged PRs (30d)
2

Description

Layout is often an expensive operation. To avoid it, views try to cache it.

Leaf views like `TextView` can cache their internal representation (lines) based on the size requested.
Group views like `LinearLayout` need, in addition, to know if any child view needs a relayout. Right now this is a boolean from `View::needs_relayout`. This means children need to hold a flag "needs_relayout", and bust this flag on any internal change. Note that this is not currently implemented everywhere it should be, so it may be subtly broken in some ways (if you resize a `BoxView` in a `LinearLayout` for example).

A potential improvement would be to, instead, return some "hash" of the state from `layout`, and take this hash in `needs_relayout`. This way, instead of requiring each view to keep a flag, we only need the parent view to keep a hash of the children layouts.

Views would use a hash of their own content + the input request. Parent views should either store the child's hash, or be able to re-compute it from their own hash + internal state. For example, a `BoxView` could hash their own state XOR a rotated hash of the child state.

This complexity comes from the need to be bi-directional (up the tree when doing layout, down the tree when asking for relayout). Alternatively, we could have a `layout_hash` method; views would not be asked if they need to re-layout, but parents would compare the children hashes with their cached ones. This is a bit simpler for views (no need to implement `needs_relayout`), but they lose some flexibility (they cannot unconditionally ask for relayout when they don't want to hash a large content).
It also makes it harder to have a default implementation that asks for a re-layout every time.

Both these methods rely on hashes rather than boolean flags, and so may add overhead in some cases:
* Currently, a large `TextView` resets the "cache ready" flag when the content is changed. `needs_relayout` is constant-time.
* Using hashes, it would either need to re-compute the hash every time, making `needs_relayout` linear in the size of the content, or cache the hash, adding (a bit) of memory overhead.

Overall the memory overhead of storing the content hash is probably fine.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.