Skip to content
This repository has been archived by the owner on Mar 3, 2023. It is now read-only.

Only update overlay instead of text editor when resize occurs #15954

Merged
merged 3 commits into from
Oct 23, 2017

Conversation

leroix
Copy link
Contributor

@leroix leroix commented Oct 20, 2017

We took care of an unnecessary loop that was occurring when an overlay was present in #15894. However, resizes of the overlay were still taking longer than needed because they were invoking .updateSync on the text editor component. In this PR, we take the approach of only updating the dimensions of the overlay element and invoking a render on just the overlay component when a resize occurs. The amount of time spent in the overlay observer callback is greatly reduced which means less time spent scripting on keystrokes. This is important because any scripting that occurs as a result of a new keystroke needs to finish well ahead of the next keystroke to avoid holding up its handling.

overlay_resizing

In the above image, the time spent in the resize observer callback is reduced from 2.36ms to 0.32ms, and the time to handle this frame goes from 11.75ms down to 9.10ms.

/cc @nathansobo

@@ -1896,6 +1896,9 @@ describe('TextEditorComponent', () => {
const decoration = editor.decorateMarker(marker, {type: 'overlay', item: overlayElement, class: 'a'})
await component.getNextUpdatePromise()

let overlayComponent
component.overlayComponents.forEach(c => overlayComponent = c)
Copy link
Contributor

@Ingramz Ingramz Oct 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like you are trying to assign the last element of array to the overlayComponent variable. Perhaps it could be grabbed from the array directly using length - 1?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, sorry for the odd syntax. overlayComponents is a Set. In Set, items don't have positions, but you can iterate over all the items in the Set. In the case of this test, I know there's only going to be one item.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very minor, but this might be slightly clearer:

const overlayComponent = component.overlayComponents.values().next().value

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yea. That's better. I hadn't looked at the Iterator api. Will Change.

updateOverlaysToRender () {
const overlayCount = this.decorationsToRender.overlays.length
if (overlayCount === 0) return null

const windowInnerHeight = this.getWindowInnerHeight()
const windowInnerWidth = this.getWindowInnerWidth()
const contentClientRect = this.refs.content.getBoundingClientRect()
for (let i = 0; i < overlayCount; i++) {
Copy link
Contributor

@Ingramz Ingramz Oct 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possible to replace with this.decorationsToRender.overlays.forEach(this.updateOverlayToRender) ? Edit: probably not, might be slower if we are after performance.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good point and switching to .forEach may have a minimal impact on performance, but I haven't measured it.

@maxbrunsfeld
Copy link
Contributor

maxbrunsfeld commented Oct 23, 2017

⚡ Awesome speedup!

@@ -804,7 +804,15 @@ class TextEditorComponent {
key: overlayProps.element,
overlayComponents: this.overlayComponents,
measuredDimensions: this.overlayDimensionsByElement.get(overlayProps.element),
didResize: () => { this.updateSync() }
didResize: (overlayComponent) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea passing in the component reference in this callback. This is such a twisty data relationship but I think this is a reasonable way to navigate it.

Copy link
Contributor

@nathansobo nathansobo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking forward to this improvement.

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

Successfully merging this pull request may close these issues.

4 participants