# Performance test of HTML CSS vs. HTML Inline vs. Stylish Elephants

**URL:** <https://discourse.elm-lang.org/t/performance-test-of-html-css-vs-html-inline-vs-stylish-elephants/1547>\
**Category:** Show and Tell\
**Created:** [July 23, 2018, 7:37pm UTC](https://discourse.elm-lang.org/t/performance-test-of-html-css-vs-html-inline-vs-stylish-elephants/1547 "2018-07-23T19:37:49Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![albertdahlin](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/albertdahlin/32/868_2.png) [@albertdahlin](https://discourse.elm-lang.org/u/albertdahlin)\
**Post date:** [July 23, 2018, 7:37pm UTC](https://discourse.elm-lang.org/t/performance-test-of-html-css-vs-html-inline-vs-stylish-elephants/1547/1 "2018-07-23T19:37:49Z")

</div>

I was curious about the rendering performance of different approaches to handle style in Elm apps.  
I’ve made a small test application that uses `requestAnimationFrame` to measure the time of each rendering cycle.

- [Try the app](https://rawgit.com/webbhuset/test-elm-performance/master/index.html)
- More details and results on [Github](https://github.com/webbhuset/test-elm-performance)

Three approaches to style are implemented and compared:

- HTML + CSS
- HTML and Inline style
- Stylish Elephants
- elm-css (PR from dmy)

I really like the API of Stylish Elephants but I wanted to find out how much it “costs” in terms of performance.

[![Performance Chart](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/2X/f/fb0f6d54574178fe1aa5143772e880a48d71eb2a.png)](https://rawgit.com/webbhuset/test-elm-performance/master/results/charts.html)

My conclusion from these tests (and some real world projects) is that SE is quite expensive in terms of performance. This can be mitigated somewhat by using `Element.Lazy` and that is something you should plan for if performance is important.

---

<div class="post-metadata">

**Author:** ![rtfeldman](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/rtfeldman/32/50_2.png) [@rtfeldman](https://discourse.elm-lang.org/u/rtfeldman)\
**Post date:** [July 23, 2018, 10:58pm UTC](https://discourse.elm-lang.org/t/performance-test-of-html-css-vs-html-inline-vs-stylish-elephants/1547/2 "2018-07-23T22:58:37Z")

</div>

> [@albertdahlin](#):
>
> My conclusion from these tests (and some real world projects) is that SE is quite expensive in terms of performance.

I think the real world projects are much more valuable information than the tests!

The biggest danger of microbenchmarks is ignoring the “it doesn’t matter in practice” possibility.

For example, virtual DOM in general adds overhead compared to handwritten DOM mutations. As it turns out, this overhead typically doesn’t matter in practice.

From this test suite we observe that SE has overhead compared to not-SE, but we already knew that! This is not new information.

The critical question is: does the overhead matter in practice?

That’s why I’d put more weight on your subjective experience on a real world project (I assume you converted to SE and noticed slowness?) compared to the objective test suite.

It would be great to see an actual app before and after using SE! I think that would potentially illuminate some interesting bottlenecks, since performance hot spots in practice are so often different from where we expect them to be in theory.

(Unfortunately it’s also a lot of work to get that comparison! It would be awesome to see `elm-spa-example` with and without SE…)

---

<div class="post-metadata">

**Author:** ![albertdahlin](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/albertdahlin/32/868_2.png) [@albertdahlin](https://discourse.elm-lang.org/u/albertdahlin)\
**Post date:** [July 24, 2018, 12:16am UTC](https://discourse.elm-lang.org/t/performance-test-of-html-css-vs-html-inline-vs-stylish-elephants/1547/3 "2018-07-24T00:16:45Z")

</div>

I agree with you, this is not a very accurate test representing how things would work in a real project. But on the other hand, real world projects have so many variables that it is not very accurate to compare them either. Unless you would have something like `elm-spa-example` implementing both. I haven’t seen anyone blogging about any real world projects using SE yet so I don’t have anything else to refer to.

I am using SE 6.0.2 for a SPA and we are noticing some performance problems. Mostly on low end mobile devices and on pages with a lot of content (tables with data etc.). Most of those problems can be improved using `Element.Lazy`. I don’t think all issues are all related to SE either. But I have the feeling some of them are.

I wanted to create a test app to get an idea of how SE behaves compared to other solutions. Something where I could use the performance profiler and get a deeper understanding on what is going on. I also wanted the tests to be repeatable in reliable way.  
Hopefully some other people will share their knowledge and experience using SE.

---

<div class="post-metadata">

**Author:** ![dmy](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dmy/32/702_2.png) [@dmy](https://discourse.elm-lang.org/u/dmy)\
**Post date:** [July 24, 2018, 8:12am UTC](https://discourse.elm-lang.org/t/performance-test-of-html-css-vs-html-inline-vs-stylish-elephants/1547/4 "2018-07-24T08:12:52Z")

</div>

I would be interested to see your benchmark with elm-css. I expect its performance degradation to be similar to Stylish Elephants.

There were some interesting points in this discussion about elm inline css performance:  
[https://discourse.elm-lang.org/t/how-to-do-css-in-elm/](https://discourse.elm-lang.org/t/how-to-do-css-in-elm/)

and unfortunately, `lazy` does not solve everything (and performance varies greatly between different browsers).

From my experience with my real-world app, if you have a page with tenths of “highly styled” elements (for example a list item flexbox container with a few flexbox children, each having margin/padding/font/color/flex set), it will matter in practice if you want a smooth experience with scrolling/hovering/menus. My strategy for now is to use `Css.Foreign` styles or SCSS for all elements that are rendered a lot (list items, icons, very common custom css styles batches) and use standard `Html.Styled` elements for everything that is rendered once.

However I believe strongly that the elm-css roadmap will improve the performance a lot and allow me to remove those work-arounds:

> [@How to do CSS in elm?](https://discourse.elm-lang.org/t/how-to-do-css-in-elm/830/17):
>
> There are three major performance optimizations I want to do for `elm-css` :
> 
> 1. [Move the compatibility checks to a phantom type](https://github.com/rtfeldman/elm-css/issues/375), so they no longer have runtime overhead.
> 2. [Hash things more efficiently](https://github.com/rtfeldman/elm-css/blob/9fa5e9cbc69cefd089556255a1cb6aa3581b43f0/src/VirtualDom/Styled.elm#L180-L181). Plenty of room for improvement there.
> 3. Use `insertRule` . This is on Evan’s radar, and he’s talked through some API ideas with me. `style-elements` would benefit from `insertRule` too.
> 
> In the vein of [Make it Work, Make it Right, Make it Fast](http://wiki.c2.com/?MakeItWorkMakeItRightMakeItFast), the current `elm-css` API has gotten positive responses on its working and working right, so it makes sense to start shifting focus to performance!

Once point `3.` has been reached (`insertRule`), I expect indeed those issues to become “it does not matter in practice” for almost everyone, whereas today, dense styled pages (like gmail for example) are likely to have issues.

---

<div class="post-metadata">

**Author:** ![dmy](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dmy/32/702_2.png) [@dmy](https://discourse.elm-lang.org/u/dmy)\
**Post date:** [July 24, 2018, 10:51am UTC](https://discourse.elm-lang.org/t/performance-test-of-html-css-vs-html-inline-vs-stylish-elephants/1547/5 "2018-07-24T10:51:05Z")

</div>

I made a pull request to add `elm-css` so we will see how it compares with the same setup but at first glance it seems quite close to stylish elephants.

I just wanted to add that I may be a minority, but as my app uses a lot of lists of accordions, I find this benchmark useful and close to my real-world use case.

What I find interesting is not that the performance is lower than “native” solutions, this is indeed expected, however the difference of the performance degradation curve shapes might be relevant, as well as the fact that pure elm solutions struggle with 60 FPS from the beginning (with 64 elements).

---

<div class="post-metadata">

**Author:** ![albertdahlin](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/albertdahlin/32/868_2.png) [@albertdahlin](https://discourse.elm-lang.org/u/albertdahlin)\
**Post date:** [July 24, 2018, 11:50am UTC](https://discourse.elm-lang.org/t/performance-test-of-html-css-vs-html-inline-vs-stylish-elephants/1547/6 "2018-07-24T11:50:41Z")

</div>

I have merged the `elm-css` implementation now. I’ve also re-run the tests and added the results to the [chart](https://rawgit.com/webbhuset/test-elm-performance/master/results/charts.html).

---

<div class="post-metadata">

**Author:** ![dmy](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dmy/32/702_2.png) [@dmy](https://discourse.elm-lang.org/u/dmy)\
**Post date:** [July 24, 2018, 12:04pm UTC](https://discourse.elm-lang.org/t/performance-test-of-html-css-vs-html-inline-vs-stylish-elephants/1547/7 "2018-07-24T12:04:08Z")

</div>

Thank you very much. What do you call “Small DOM update” and “Large DOM update” in the charts? (I suppose small is opening an element, large is rendering the full list?)

I find interesting that elm solutions struggle with the “view” part for small updates. I think it shows that this is not really the VDOM that is slow, but more the re-computing of the style node(s) (even if only one element style is actually changed). So if I’m not wrong, this benchmark is actually more about elm inline styling (which actually interests me more than VDOM).

---

<div class="post-metadata">

**Author:** ![albertdahlin](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/albertdahlin/32/868_2.png) [@albertdahlin](https://discourse.elm-lang.org/u/albertdahlin)\
**Post date:** [July 24, 2018, 12:52pm UTC](https://discourse.elm-lang.org/t/performance-test-of-html-css-vs-html-inline-vs-stylish-elephants/1547/8 "2018-07-24T12:52:23Z")

</div>

You are correct, “Small Update” is opening an accordion. “Large Update” is re-render of the whole view, when switching between implementations.

I would guess the reason for SE and elm-css spending more time in the view function is that they do a lot of work. The two HTML implementations just generates VDOM nodes. SE and elm-css do a lot of List.fold, Dict and Set operations and string concatenation before generating VDOM.

You could also look at it this way:

To perform the same effect (for example render 64 accordions), both HTML/CSS and elm-css completes the test with 60 FPS, but the latter do a lot more work to accomplish this. This might not be an issue in some cases.

HTML+CSS, 64 accordions

![html-css](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/2X/9/9edeffd64cf2a798484cd2d2406d08ede328dc6c.png)

Elm CSS, 64 accordions  
 ![elm-css](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/2X/4/4d52d62093ed03d8098886ce242f467d4ad826c7.png)

These are my real world experiences from using Stylish Elephants:

- If you are doing animations or reacting to mouse / touch move, you will definitely run into performance problems. You would probably be better of with native css or something like web components. Check this [great talk](https://www.youtube.com/watch?v=tyFe9Pw6TVE).
- If your UI consists of many nodes, for example large tables or trees, you will run into problems on mobile devices. Desktop might get by.
- You might also run into problems on low end devices when the phone is doing stuff in the background since the performance headroom is very small.

---

<div class="post-metadata">

**Author:** ![dmy](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/dmy/32/702_2.png) [@dmy](https://discourse.elm-lang.org/u/dmy)\
**Post date:** [July 24, 2018, 12:56pm UTC](https://discourse.elm-lang.org/t/performance-test-of-html-css-vs-html-inline-vs-stylish-elephants/1547/9 "2018-07-24T12:56:58Z")

</div>

My conclusions using `elm-css` are pretty much the same.

Also using `Html.Styled.Lazy` at the item level doesn’t really solve the issue for lists/tables/trees because it will force to render a style node for each item, and then this is the browser that struggle to parse all of those and recompute the styles (note that firefox is a lot better than Chrome since Quantum for this).

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/1X/50a05e53677a2c3b47776d7abd0f113eb50193a1.png) [@system](https://discourse.elm-lang.org/u/system)\
**Post date:** [August 3, 2018, 12:57pm UTC](https://discourse.elm-lang.org/t/performance-test-of-html-css-vs-html-inline-vs-stylish-elephants/1547/10 "2018-08-03T12:57:00Z")

</div>

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.
