Skip to content

Comment on Solidjs – JavaScript UI Library

Comments

Heck of a library, and its creator, Ryan Carniato, is a very smart engineer who works on both Marko[0] and solidjs. He's really patient and answers my random questions on Twitter pretty reliably, I have to say I appreciate it!

The performance that SolidJS eeks out of the DOM is really next level.

I think it could use a small augment in the docs about migrating from React to SolidJS, but all around the project is very approachable and fantastic, and its fast

[0]: https://markojs.com/

The performance that SolidJS eeks out of the DOM is really next level.

Kind of a weird way of putting it. Intuitively any framework abstracting concepts on top of DOM manipulation has to be slower than direct DOM manipulation.

But yes in comparison to other frameworks, the benchmarks they make do look impressive.

Now I'm curious to do some benchmarking of my own.

That's kind of why the entire virtual DOM concept came about, because it was faster than direct DOM manipulation. Essentially batched updates to the DOM were faster than ad-hoc updates.

Now React is 8 years old and browsers have improved a lot since then so I imagine the gains might not be what they used to be. But at the time it was huge.

Virtual DOM came about since it offered a simplistic top down view = fn(state) model without terrible performance. Other top down renderers were terribly inefficient and this built on that. It was never innately faster than targeted direct DOM manipulation. It was just compared to other approaches that were innately built on diffing as well. And things like reading from the DOM can cause reflows and other terrible performance bottlenecks.

Fine-grained reactivity existed back then and was more performant for updates. Always was. Just had its own issues since pre-MobX we didn't see implementations in JavaScript which provide glitchfree execution guarantees. So Virtual DOM was a great invention but I think it was misrepresented early on. That's what got me to start working on Solid. I knew the performance was there without a VDOM from day one. I'd seen it. So when Knockout started waning in popularity 2015/2016 I started working on a replacement.

That perception of the DOM/VDOM situation is and always was false. React was always slower at runtime than a carefully-engineered system designed for performance.

As Dan Abramov said a couple of years later <https://medium.com/@dan_abramov/youre-missing-the-point-of-r...>, people were missing the point of React: it was never about VDOM; rather, that was a cost that at the time they reckoned had to be paid in order to write reliable code in an immediate mode style, because if you tried doing that without DOM reconciliation the result would be atrociously bad. VDOM came about because the alternative (the consistently faster alternative, I may add) entailed things like explicit DOM mutation that was far too easy to make mistakes with, and reactive data flow was generally even buggier. It was a carefully-chosen trade-off: shedding some performance, for greater robustness and ease of use.

“DOM is slow, VDOM is fast” was a straw man comparison that entered the public perception but which the React team mostly stayed well clear of: almost no serious systems have ever used the DOM directly in the immediate mode style, because it has obvious and serious problems in both performance and transient UI state like scroll and caret positions and element focus (… and transient state things are problems for all immediate mode interfaces, not just DOM ones: escape hatches are fundamentally required).

Was VDOM worth the cost at the time, compared with the other options then available? For most people, probably. And even for the rest, React presented useful food for thought that led to other options improving too. Is VDOM worth the cost now? Well, I’m with Rich Harris that VDOM is pure overhead <https://svelte.dev/blog/virtual-dom-is-pure-overhead> and that we have more efficient ways of doing things now.

Wasn’t a separate big motivation that reading from the real DOM (in order to generate a diff with the new intended DOM) is also slow?

The DOM used to be slow, incredibly slow, but that was a very long time ago when JavaScript only executed as an interpreted language. The DOM has been insanely fast even since before React was born. Using micro-benchmarks you can see that DOM access, when not using query selectors, tops out at around 45 million ops/s in Chrome and between 700 million to 4 or 5 billion ops/s in Firefox depending upon your CPU and ram. That is fast. No higher level framework will improve upon that.

Back in the day when the DOM was slow the primary performance limitation was accessing everything through a single bottleneck, the document object. To solve for this the concept of document fragments was invented. These aren't used anymore because the DOM is insanely fast and modern implementations (popular frameworks) are so incredibly slow. You aren't going to achieve a technology solution to a people problem.

The first big misconception of DOM performance is the difference between DOM interaction and visual rendering. Visual rendering is fast now because its offloaded to the GPU but its still far slower than accessing and modifying the DOM. As an example set an element to display:none and then perform what ever DOM modifications you want to it. Those changes have no visual rendering, are still DOM manipulation, and are insanely fast. You can measure this with a microbenchmark tool.

The second big misconception of DOM performance is how to access the DOM. The fastest means of access are the old static DOM methods, like: getElementById and getElementsByClassName. Query selectors will always impose a huge performance penalty when there are standard methods to do the same job and a minor performance boost when there aren't. The querySelectorAll method compounds that performance penalty. The performance penalty is present due to string parsing of the selector as necessary to convert that into something vaguely equivalent to the static methods, which is a step on each operation the static methods do not require. The minor performance to access things, such as by attribute, is achieved because there isn't a single static method equivalent and more steps must be taken compared to the parsed string result of the selector, but that performance boost is exceedingly minor (16x at most).

Usually developers prefer slower means of access to the DOM due to preferential bias to declarative approaches to programming. There isn't a performance tool to fix developer bias.

If you want both performance and less intimidating approaches to DOM access you can create aliases that solves for code reuse with more friendly names, but you will still need to understand the concept of a tree model.

Fair enough, I don't retract the ethos of this statement, but really it should: as far as abstractions go, SolidJS is a very performant framework, arguably more so than any other framework out there right now

Oh,I agree so much here. It was 2 years back when I had looked at SolidJS. It was a simple project and had Bootstrap for a couple of pages and instead of JQuery or Mithril, I put in SolidJS. Was stuck on few reactive issues. Ryan was so quick to help me and also explain few things which really helped me.

Interesting how does this compare to Mithril? I have yet find anything that is more performant than Mithril. Never heard of solid. How is it?

Mithril is reasonably fast, but there are plenty of faster options like Solid, Inferno, Preact, or Svelte.

https://krausest.github.io/js-framework-benchmark/current.ht...

IMO the best thing about Mithril is that it doesn't have reactivity, much like Imba. This allows you to define state with pure vanilla objects and classes. Also that it includes an HTTP client and router in just 10kB.

It's really verbose though compared to Svelte.

[Mithril.js author here]

FYI, the krausest benchmark is known among framework authors to be not very good (it weighs some aspects much more heavily than others and has been gamed by various toy-ish "frameworks" that aren't all that practical in real life).

With that said, people obviously use React and even Ember (which are on the slower side of the krausest rankings) out in the wild and they're generally fine frameworks: asciinema-style "render-a-huge-grid-at-60fps" is very much a niche use case that 99.9% of people don't have.

I think the most accurate way to describe Mithril.js is that it aims to be a "get-out-of-your-way" sort of tool, in the sense that if things go wonky, you can generally reason about the low level reason as to why that is the case. For example, in Mithril.js, `render` is not just a first-class concept but an explicit API. So if you ever run into an issue where the template doesn't update for whatever reason, you can intuitively infer exactly what to do to unblock yourself. No need to reason about stale closures when debugging useEffect, observable/signal composition, or similarly complicated mental models. Reactivity, specifically, is great for squeezing performance from needle-in-the-haystack sort of updates when you have humongous haystacks, but it does also have caveats: if Svelte ever doesn't update the template for some reason, the mental model required to understand reactivity membership graphs and reactive bindings and where the compiler has jurisdiction and all that jazz are quite a bit more complicated than "ok fine, just slap a render call in this library's event handler".

The thing you said about vanilla objects follows from those principles: as a JS person, you know how objects work so you're never going to run into cognitive dissonance about the semantics of your primitives.

The verbosity thing I think is more a testament to Svelte being terse than anything else. Mithril.js isn't really verbose compared to other frameworks, IMHO.

</two-cents>

run into cognitive dissonance about the semantics of your primitives

Thank you for stating that. Seems like Mithril isn't just fast for processor, rather it is a fast for mental processing.

I always say Mithril is a sushi chef knife. It's wonderful if you know what you're doing, but you can cut yourself badly if you don't.

In more popular frameworks like React, Vue, and Angular, there are multiple tools that give you a structure. In Mithril you're free to do whatever you want.

Personally, I love that freedom. It's also one of the reasons I love Svelte, since it tends to get out of the way.

Hey Leo

I agree with all your points, of course. I don't think I ever stated that Mithril was slow or verbose in an absolute sense.

Interested as well, Mithril seems plenty fast for my use case. One area I believe I read about where VDOM/Mithril is faster is dealing with dynamic list data. E.g. you have a list of items you're rendering (probably keyed in Mithril), and you append a new one, it'll render faster with VDOM then solid because the diff process will be faster than whatever solid is doing.

Solid's diff algorithm generally is faster(or atleast very comparable) than Mithril's. We test very well in list benchmarks like: https://krausest.github.io/js-framework-benchmark/current.ht.... We are also fast at node creation using pre-compilation to prepare the nodes in a way that can be created more efficiently.

Interesting, thank you for the links and clarification. May need to revisit solid then! What about rendering things that aren't rendered by solid, like markdown rendering via commonmark? Also, Mithril streams is a huge part of my app, will I miss it with Solid?

Hey Solid's reactive system uses Signals which are different than streams but work in similar use cases. Streams are slightly more oriented to transformation than synchronization. Most stream libraries could be used with Solid with a bit of an adapter on the end to connect to the templates as they are a good tool for managing global state.

All that being said. If you are happy with Mithril stick with it. It sounds like it's done everything you needed. I have a lot of respect for it's minimalist approach and its author is one of the most insightful and helpful people I've come across since getting into JavaScript frameworks.

If you are interested in trying something different. Check out our tutorials on the site and see how you feel about it. It is a little bit different type of framework.

Interesting but your comment on doco and the fact that you need to ask the dev on twitter is a huge turn off.

Documentation > performance for most business applications, because it's developer performance. I don't have time to reverse engineer some uber nerd's SIMD optimized world wonder, I have things to ship.

When I go to https://markojs.com in Safari (14.1.2), the CPU load on my MacBook Air goes up above 100%. If I use the Brave browser, the CPU load is closer to 25%. Still too much.

AboutSource Built by g1lg1l

Hackerly is an independent reader for Hacker News, built on the public HN API. Not affiliated with Y Combinator.