bigskysoftware / bigskysoftware/idiomorph
Idea for a massive speedup
- Dominant language
- HTML
- Stars
- 1.1k
- Forks
- 57
- Avg merge
- 9h 58m
- Merged PRs (30d)
- 4
Description
Hi folks! I'd like to open some discussion about an idea I've been kicking around for a while to massively improve the performance of morphs.
### Background:
I've noticed that in many real-world page morphs, the vast majority of the html doesn't change between old and new. So we're wasting a ton of CPU recursing down DOM subtrees that ultimately don't change at all.
### Idea:
The basic idea here is to skip morphing entire DOM trees if they're equivalent. Effectively, it'd be something like this, except baked into idiomorph:
```javascript
beforeNodeMorphed: (oldNode, newNode) => {
if (oldNode.tagName && oldNode.outerHTML == newNode.outerHTML) {
return false
}
}
```
### Pros:
* Massive, massive speedups across most use-cases. In some tests in https://bardtracker.com , I'm seeing 10x in "normal" morphs, and even upwards of 100x(!) in pathological cases where projects have many dozens of tickets.
* It normalizes/removes the special case of hidden value state being cleared on morph. This is also a con, more below.
### Cons:
* We'd have to introduce a breaking change: Morphing `` -> `` should NOT clear the value property. Right now, it does.
However, this is an outlier in terms of how we're handling hidden state (we otherwise aim to preserve it), and its been proposed to change this already: https://github.com/bigskysoftware/idiomorph/issues/27 . This may introduce friction to the consumer of the library, though, TBD.
* `beforeNodeMorphed` would no longer be called on the many many elements that are now being skipped
### Open questions:
* How disruptive would the value breaking change be, in practice?
* Are there any important use-cases for `beforeNodeMorphed` being called on an element that's not being changed?
* Could this actually be a performance regression in real-world scenarios? I can imagine two large different documents being a pathological case for this, resulting in many extra `.outerHTML` calls with no benefit. They'd still have to line up enough so that morphing is occurring, rather than just adds and removes, so maybe its not realistic. Can we construct a realistic scenario where this becomes pathological?
* Are there any other consequences to this that I've missed?
### Proposal:
* Introduce this behavior as a new off-by-default option in v0.8.0
* If all goes well, flip it on by default for the next non-patch release after that
### Request for comments!
Thoughts, comments, questions?
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.