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

prism-line-highlight is slow on resize because it forces a reflow for every #1860

Closed
justinbmeyer opened this issue Apr 11, 2019 · 3 comments

Comments

@justinbmeyer
Copy link

justinbmeyer commented Apr 11, 2019

Information:

  • Prism version: 1.16.0.
  • Environment: Chrome Browser

Does the latest version of Prism from the download page also have this issue? I'm using it from npm.

Description

The line-highlight plugin is causing multiple forced reflows every time I resize a page. I have about 29 highlighted code blocks on the page. You can see this and the warning here:

image

Looking at the code, there is a lot of repeated read layout and write layout loops around here:

line.style.height = (endNode.offsetTop - startNode.offsetTop) + endNode.offsetHeight + 'px';

This is in a for-loop for each highlighted range, which is in another for loop for each code block.

Could this be changed to read the layout all at once and write the layout all at once? If interested, I will submit a PR for this. Here's an example that shows the difference (500ms to 5ms) if batched read/writes are used.

Thanks!

@Golmote
Copy link
Contributor

Golmote commented Apr 22, 2019

Hello! Thanks for opening this issue. If you're willing to submit a PR to fix this, please do, it is much appreciated!

@justinbmeyer
Copy link
Author

Here's the code (a PR will be created tomorrowish). It changes my highlight time from about 400ms to about 2ms on the slowest performing page.

In short, I added a little helper that allows me to store calling a function or setting a property:

function makeActions() {
	var actions = [];

	return {
		actions: actions,
		apply: function(fn, context, args){
			actions.push(function(){
				fn.apply(context, args);
			});
		},
		set: function(obj, key, value) {
			actions.push(function(){
				obj[key] = value;
			});
		}
	};
}

Then, instead of mutating the DOM, I use the helper:

// line.setAttribute('data-range', currentRange);
action.apply(line.setAttribute, line,['data-range', currentRange]);

// line.style.top = startNode.offsetTop + 'px';
action.set(line.style, "top",  startNode.offsetTop + 'px');

And then return these actions to be called later:

		var actions = [];
		Array.prototype.forEach.call(preElements, function (pre) {
			actions.push.apply(actions, highlightLines(pre) );
		});
		actions.forEach(function(action){
			action();
		});

@RunDevelopment
Copy link
Member

Resolved by #1865.

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

No branches or pull requests

3 participants