bigskysoftware / bigskysoftware/idiomorph

Idea for a massive speedup

Open
#144 6 comments 1 reaction 0 assignees View on GitHub
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.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.