Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 18 commits into from
May 16, 2017

Conversation

Tyriar
Copy link
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
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
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

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

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

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

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

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

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

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

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

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

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
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
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
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
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
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
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
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
@@ -760,7 +760,9 @@ Terminal.loadAddon = function(addon, callback) {
* character width has been changed.
*/
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
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
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

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

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