Skip to content

Keep row spans in an object pool to reduce garbage collection by reusing DOM nodes#450

Merged
Tyriar merged 18 commits intoxtermjs:masterfrom
Tyriar:449_keep_span_pool
May 16, 2017
Merged

Keep row spans in an object pool to reduce garbage collection by reusing DOM nodes#450
Tyriar merged 18 commits intoxtermjs:masterfrom
Tyriar:449_keep_span_pool

Conversation

@Tyriar
Copy link
Copy Markdown
Member

@Tyriar Tyriar commented Jan 4, 2017

Fixes #449
Fixes #467


This PR adds and utilizes an object pool in Terminal.refresh so that all the spans and text nodes are not being thrown away sometimes milliseconds later.

This introduces one change in behavior in that it wraps plain text in a span, not a text node as there seemed to be issues with adding text nodes only containing  . I think this should have minimal impact on perf though.

A good illustration of it is action is the below shot of the DOM after a for x in {1..500000}; do echo $x; done, this would previously have generated 100-1000 DOM elements (the number is low due to refresh rate limiting and frame skipping) but you can see the IDs which are assigned in sequence are all in the double digits as the nodes are being reused:

image

@Tyriar Tyriar added the work-in-progress Do not merge label Jan 4, 2017
@Tyriar Tyriar self-assigned this Jan 4, 2017
@Tyriar Tyriar requested a review from parisk January 4, 2017 17:48
@Tyriar
Copy link
Copy Markdown
Member Author

Tyriar commented Jan 4, 2017

Testing this is a little more involved, putting on hold until the other more important perf PRs land.

@Tyriar Tyriar modified the milestone: 2.3.0 Jan 4, 2017
@Tyriar Tyriar added work-in-progress Do not merge and removed work-in-progress Do not merge labels Jan 9, 2017
@Tyriar
Copy link
Copy Markdown
Member Author

Tyriar commented Jan 9, 2017

This is particularly tricky to perf test. What (I think) I'm seeing is a slight degradation in overall command speed (~5%?), more DOM nodes created (which needs to be investigated) but less JS memory usage/GC. I do think it's a valuable change, it needs more work though.

@Tyriar Tyriar removed this from the 2.3.0 milestone Feb 8, 2017
@coveralls
Copy link
Copy Markdown

Coverage Status

Coverage increased (+0.2%) to 68.912% when pulling 23e6a47 on Tyriar:449_keep_span_pool into 64d3c08 on sourcelair:master.

@coveralls
Copy link
Copy Markdown

Coverage Status

Coverage increased (+0.2%) to 68.879% when pulling 3baa6b9 on Tyriar:449_keep_span_pool into 64d3c08 on sourcelair:master.

@coveralls
Copy link
Copy Markdown

Coverage Status

Coverage increased (+0.2%) to 68.879% when pulling abcdf3e on Tyriar:449_keep_span_pool into 2221f70 on sourcelair:master.

@coveralls
Copy link
Copy Markdown

Coverage Status

Coverage increased (+0.2%) to 68.936% when pulling 508d3ab on Tyriar:449_keep_span_pool into 6dad013 on sourcelair:master.

@coveralls
Copy link
Copy Markdown

Coverage Status

Coverage increased (+0.2%) to 68.969% when pulling 6c8949b on Tyriar:449_keep_span_pool into 6dad013 on sourcelair:master.

@coveralls
Copy link
Copy Markdown

Coverage Status

Coverage increased (+0.2%) to 68.985% when pulling c887c6e on Tyriar:449_keep_span_pool into 6dad013 on sourcelair:master.

@coveralls
Copy link
Copy Markdown

Coverage Status

Coverage increased (+0.2%) to 68.952% when pulling 9ec8974 on Tyriar:449_keep_span_pool into 6dad013 on sourcelair:master.

@coveralls
Copy link
Copy Markdown

Coverage Status

Coverage increased (+0.2%) to 68.952% when pulling 4781484 on Tyriar:449_keep_span_pool into 6dad013 on sourcelair:master.

@Tyriar Tyriar removed the work-in-progress Do not merge label May 14, 2017
@coveralls
Copy link
Copy Markdown

Coverage Status

Coverage increased (+0.2%) to 68.952% when pulling 5fb3097 on Tyriar:449_keep_span_pool into 6dad013 on sourcelair:master.

@coveralls
Copy link
Copy Markdown

Coverage Status

Coverage increased (+0.2%) to 68.952% when pulling 5fb3097 on Tyriar:449_keep_span_pool into 6dad013 on sourcelair:master.

@Tyriar
Copy link
Copy Markdown
Member Author

Tyriar commented May 14, 2017

This is ready to review/merge.

Update:

  • The performance impacts of the object pool are negligible - so close they're difficult to test effectively, however this refactor improves the quality of the code significantly.
  • Single-width unicode characters not have their width explicitly set which fixes Better support for unicode characters #467 (an adoption blocker for Hyper).

@Tyriar Tyriar added this to the 2.7.0 milestone May 14, 2017
@Tyriar
Copy link
Copy Markdown
Member Author

Tyriar commented May 14, 2017

On performance of unicode heavy apps like vtop, rendering and painting time goes down (presumably due to reuse of spans) but scripting time goes up (wrapping almost all chars in spans). The frames take a little longer (+~30%), but it's actually usable now 😉

Before:

screen shot 2017-05-14 at 2 51 30 pm

After:

screen shot 2017-05-14 at 2 51 41 pm

parisk
parisk previously requested changes May 16, 2017
Copy link
Copy Markdown
Contributor

@parisk parisk left a comment

Choose a reason for hiding this comment

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

Great job done here. It was one of the most enjoyable Pull Requests to read it's code.

The only thing I would require is documenting all methods of the DOM Element Object Pool, as we might get back to it in the future.

After this, it's ready to merge 👍 .

this._inUse = {};
}

public acquire(): HTMLElement {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Document this method please, with a comment above this line.

return element;
}

public release(element: HTMLElement) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Document this method please, with a comment above this line.

this._pool.push(element);
}

private _createNew(): HTMLElement {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Document this method please, with a comment above this line.

return element;
}

private _cleanElement(element: HTMLElement): void {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Document this method please, with a comment above this line.

src/xterm.js Outdated
Terminal.prototype.updateCharSizeCSS = function() {
this.charSizeStyleElement.textContent = '.xterm-wide-char{width:' + (this.charMeasure.width * 2) + 'px;}';
this.charSizeStyleElement.textContent =
'.xterm-wide-char{width:' + (this.charMeasure.width * 2) + 'px;}' +
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Non-blocking: Should we use template literals here as well?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

👍

@coveralls
Copy link
Copy Markdown

Coverage Status

Coverage increased (+0.2%) to 68.952% when pulling 1a777ed on Tyriar:449_keep_span_pool into 6dad013 on sourcelair:master.

@coveralls
Copy link
Copy Markdown

Coverage Status

Coverage increased (+0.2%) to 68.952% when pulling aad8439 on Tyriar:449_keep_span_pool into 6dad013 on sourcelair:master.

@Tyriar Tyriar merged commit a95ac99 into xtermjs:master May 16, 2017
@Tyriar Tyriar deleted the 449_keep_span_pool branch May 16, 2017 17:12
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

Successfully merging this pull request may close these issues.

3 participants