Jamie Gaskins

Ruby/Rails developer, coffee addict

Followup: Turbolinks vs the Virtual DOM

Published Mar 13, 2016

A couple weekends ago, I wrote an article comparing re-render times between Turbolinks and Clearwater. It wasn't focused on Clearwater, exactly, but I'd just gotten done with some work on it so that's where my mind was.

Before I get too far into this, I want to point out that I wasn't trying to call out Nate as the sole human being that carries the point of view that Turbolinks is necessarily better than a virtual DOM. I've seen at least a dozen people tweeting about how a vdom is too complex, likely spawned by DHH's tweets on the subject. Nate's tweets just happened to be the ones that spurred me into running this experiment in the first place. I'd like to take this opportunity to apologize to Nate for making it look like I'm calling him out.

I posted an example app, which proved to be more problematic than I'd realized because, in true internet fashion, people then began scrutinizing it in an effort to find many ways to tell me I'm doing it wrong.

In their defense, I didn't make it abundantly clear that I was comparing only the performance of re-rendering and that first render was completely out of scope of the article. I feel like I made my point clear that re-rendering with a virtual DOM was faster, but I didn't make it clear that re-rendering on navigation was the sole focus.

In my defense, I didn't realize I had to, considering that's the only thing for which Turbolinks is in any way useful.

Let's go into a couple of examples of people's responses to that article:

totally unfair comparison though https://turbolinks-vs-clearwater.herokuapp.com/ 1 second wait to click "turbolinks" 8 second wait after clicking "clearwater" — @samsaffron

It's unfair if I cared about first-render time. Of course Turbolinks is great for the first render. It's almost the same performance on first render as not using Turbolinks — or any other JavaScript — because it's really only useful for reusing the existing JS and CSS in memory and only throwing away the DOM.

A virtual DOM, when you're not server-rendering, is always going to lose the first-render race. I didn't spend any time on first-render optimizations because I only spent an hour or so on the app to begin with. I didn't gzip it or send only the initial data needed to render the list (such as ids and titles). This would've saved a whole lot of that first-render time. In light of that, I'm surprised it only took 8x because it sent a lot of data.

fairer comparing "click->ajax->json->render" vs "click->render" vs "click->pjax->replace" — @samsaffron

This is probably the fairest criticism I received. He's saying I should've included an AJAX call in there to compare fetching from the server with Turbolinks.

If you look at the Turbolinks performance screenshot, though, you'll notice there is nothing between the click event and the JS to render it to the DOM. I eliminated the request by using a link I'd previously clicked so Turbolinks would have it cached. This allowed me to focus on CPU usage.

Adding server requests convolutes the experiment with more variables for which we can't control. Sam would see very little difference between a Turbolinks request and an AJAX+vdom-render, considering he lives in Australia, which is about the farthest you can get from the Heroku infrastructure without leaving the atmosphere. The latency he'd see would fuzz the results, making them look potentially almost the same. However, someone on the east coast of the US who has 20ms latency to the server would see something quite different.

so they're using Clearwater caching to get that speed, but not Rails template caching? 💩 — @seanlinsley

"Why isn't this person making every possible optimization to this clearly contrived app?"

Come on.

Maybe they didn't realize that I was using a Turbolinks-cached endpoint and that any server round-trip time, if it did happen, wouldn't be factored into the JS+render time, which only counts CPU usage and not time spent on I/O. But even if they don't, that's really reaching to find something to complain about.

It goes the other way, too

There was even some destructive criticism directed at Nate based on very little context. Nearly every single person I saw who jumped into this with more than a "hey, this looks interesting" jumped straight to the conclusion that no thought was put into this by anyone other than them.

In fact, the one person who had the most level head on this whole topic was the person whose tweets I was criticizing in the first place. Nate asked me several questions about Clearwater to make sure he had enough information before he posted a response to mine. I'm sure he wants to mention the tradeoffs of either approach. I think it'll be an awesome read and I hope he can find the time to finish writing it.

But please, when you read a technical comparison of two technologies, please think about it a bit and assume the author has done the same. Ask questions before criticizing; they may have considered the conclusion you're jumping to but just haven't articulated themselves enough.