Skip to content

Revisit setAttribute vs setting properties #3750

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

Closed
Rich-Harris opened this issue Oct 19, 2019 · 1 comment
Closed

Revisit setAttribute vs setting properties #3750

Rich-Harris opened this issue Oct 19, 2019 · 1 comment
Labels
compiler Changes relating to the compiler perf stale-bot temp-stale

Comments

@Rich-Harris
Copy link
Member

A while back we stopped using direct property access to change attributes, and started using setAttribute everywhere, via the attr helper. The reason for this was that we want null/undefined attributes (i.e. class={maybe_undefined}) to be removed from the element, and there's no way to achieve that via property access (el.className = null doesn't remove the attribute).

While poking around a benchmark the other day, I learned that el.setAttribute('class', foo) is significantly slower than el.className = foo.

So now I'm thinking that we need to consider secret option 3: having a separate function for each attribute that's settable via property:

function remove_attribute(node, name) {
  node.removeAttribute(name);
}

function set_class(node, value) {
  if (value == null) remove_attribute(node, 'class');
  else node.className = value;
}

// later...
set_class(div, ctx.foo);

This obviously means the cost of using a single class attribute increases, since we need the additional helper. Over the course of an app, that cost gets amortized:

// unminified
function set_class(node, value) {
  if (value == null) remove_attribute(node, 'class');
  else node.className = value;
}

attr(div, 'class', ctx.foo);
set_class(div, ctx.foo);

// minified
function d(a,b){b==null?e(a,'class'):(a.className=b)} // 53 bytes

a(b,'class',c.foo);
d(b,c.foo); // 8 bytes fewer per occurrence

This benchmark shows that, in cases where values are recalculated but haven't changed, caching values in memory (and only updating the property when they change) yields the best performance, followed by checking the existing property.

Screen Shot 2019-10-19 at 14 37 11

Of course, in many apps, if values are being recalculated it's because they likely have changed, in which case not bothering with caching or comparing to the existing property value is obviously faster, but probably not by such a huge margin that it's worth penalising the alternative case. Screenshot of results here (no link because ESBench won't let me save for some reason):

Screen Shot 2019-10-19 at 14 33 46

Either way, property access beats setAttribute handily. (Though I haven't tried other pairs other than class/className...)

Thoughts?

@stale
Copy link

stale bot commented Dec 28, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale-bot label Dec 28, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler Changes relating to the compiler perf stale-bot temp-stale
Projects
None yet
Development

No branches or pull requests

3 participants