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

[Benchmark] DOM rendering performance #3

Closed
3 tasks done
robinweser opened this issue May 22, 2016 · 11 comments
Closed
3 tasks done

[Benchmark] DOM rendering performance #3

robinweser opened this issue May 22, 2016 · 11 comments

Comments

@robinweser
Copy link
Owner

robinweser commented May 22, 2016

In order to get the best (DOM) rendering performance possible, we should generate some basic benchmark to test different methods of adding a new ruleset to a CSSStyleSheet.

Methods

  • node.sheet.insertRule(rule)
  • node.textContent = updatedCSS
  • node.textContent += rule
@robinweser robinweser added this to the Backlog milestone May 31, 2016
@nathanmarks
Copy link

nathanmarks commented Jun 2, 2016

@rofrischmann FWIW: https://bugs.chromium.org/p/chromium/issues/detail?id=387952#c6 -- and it's tagged as "WontFix"

@robinweser
Copy link
Owner Author

I see. So what you're saying is not to use insertRule if possible?

@nathanmarks
Copy link

@rofrischmann Using that API severely limits dev tools usage, can't even toggle the properties in chrome:

image

@robinweser
Copy link
Owner Author

robinweser commented Jun 2, 2016

I've created a small benchmark to generally check the speed (https://gist.github.com/rofrischmann/15073c4297e0bbd6e0732e4903655d7c).
You might want to run this using es6fiddle.
Seems like insertRule is many times faster actually.

[Log] Running 10 times...
[Debug] insertRule: 0.391ms
[Debug] concatTextContent: 1.055ms
[Debug] overwriteTextContent: 0.970ms

[Log] Running 100 times...
[Debug] insertRule: 0.338ms
[Debug] concatTextContent: 17.685ms
[Debug] overwriteTextContent: 18.403ms

[Log] Running 1000 times...
[Debug] insertRule: 3.450ms
[Debug] concatTextContent: 857.059ms
[Debug] overwriteTextContent: 791.947ms

[Log] Running 10000 times...
[Debug] insertRule: 49.079ms
[Debug] concatTextContent: 92909.438ms
[Debug] overwriteTextContent: 85547.511ms

Well, we're talking about milliseconds, but as we know it we should consider using insertRule for production. There's no problem in keeping the textContent method for development. It even helps to keep using middleware without changes e.g. beautifer or logger.

@nathanmarks
Copy link

@rofrischmann Thanks for running those benchmarks, very interesting!

Couple of quick Qs:

  1. Have you tried using this lib yet with HMR or redux time time travel?
  2. How does the lib solve specificity concerns when nesting components and passing classNames?

@nathanmarks
Copy link

What do you think of your approach here vs your approach in react-look? Seems like the libs both cover some of the same ground. Is there a reason you decided to start up this project too?

@robinweser
Copy link
Owner Author

Well yeah, I am experimenting since I started with Look and came up with the solution that generating CSS still is the best way, but needs to be more dynamic.
Yet Look somehow got kind of verbose (I was really overwhelmed by JavaScript, ES2015 and Open Source in general as I just started learning all of it).
I've learned a lot since then and lately asked myself why Look is so restricted to React actually.
I already experimented with an universal API earlier, but had no idea how to actually solve certain problems.
Fela now is kind of a well planed version of all my ideas in a minimal amount of code with not many features.
What I like is that Fela runs free of any library and does not require a lot of additional markup, wrapping or helpers. Wrapping the whole Component and all the stuff just gets complicated so fast that its hard to keep track (and updated docs) even for myself as a maintainer, but I am not saying that I will not further improve and support Look for now. Might just slowly migrate to Fela.

Actually I did not test it with HMR or time travel, but might do this. HMR should work I guess, but for time travel we might need to implement another middleware (which is also one of the cool new features that Look does not provided that easy).

I guess you will better understand what I mean when the React bindings are out. It doesn't really have any special fancy API it just works :p

I will update this comment at home to answer all your questions correctly. Is there a special specificity problem you are interested in?

@nathanmarks
Copy link

nathanmarks commented Jun 2, 2016

Thanks for the detailed response! You have reflected some of my own fears about react-look there.

Here's some pseudocode demonstrating the specificity question/concern:

// assume `classes` holds fela classNames for this react component

const Button = (props) => (
  <button className=${classnames(classes.button, props.className)}>
    {props.children}
  </button>
);
// assume `classes` holds fela classNames for this react component

const MyBox = () => (
  <div className={classes.base}>
    <Button className={classes.button}>Hello</Button>
  </div>
);

How does fela handle the specificity issue there when overriding styles via passing another classname created by fela?

@oliviertassinari
Copy link

@rofrischmann Could we use node.sheet.insertRule(rule) in production and another method in development? Or that would be too error prone?

@robinweser
Copy link
Owner Author

robinweser commented Jun 2, 2016

@nathanmarks That seems to be an example I did not consider to handle actually, maybe I got the term specificity wrong at all. Do you have any example of libs/ideas that handle this case wisely?
Yet I think it perhaps is a problem of design in general, I could just come up with some ideas to solve this case, but I am not sure if you could apply it everywhere. Would be interesting to actually test out some real use cases soon.

@oliviertassinari Yeah, I was think about that. I already eliminate all NODE_ENV != 'production' paths while building, so that should not be a problem. I though might get too complex. An alternative would be to just implement a simple middleware that handle modifies the change event action. Let me know what you think of both ways.

@nathanmarks @oliviertassinari Feel free to join me on Gitter for further chatting :P

@nathanmarks
Copy link

@rofrischmann I'll find you on there

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