yonkeltron.com

Temporary exile

Quick Thoughts on Client-side Template Rendering

Very recently, there was a discussion posted about the Google+ team’s usage of client-side template rendering. The discussion continued on the DailyJS blog which asked a few questions about appropriate usages of client-side rendering for performance, design or philosophical reasons. This got me thinking enough to write down some of my thoughts as I have recently experimented with client-side rendering for both personal projects and work. For reference, I have been toying with underscore templates.

For this discussion let’s define performance as having two components:

  • Resource utilization
  • Speed

Naturally, in this simplification both items overlap quite a bit and misrepresent the actual nature of the issue, blah, blah, yadda, yadda. Ok so the computer scientist faculty taught us all that optimization entails either maximizing something or minimizing something. Let’s discuss performance optimization in the general case by optimizing each performance component separately. Explicitly: minimizing resource utilization and maximizing speed.

With respect to resource utilization, consider the example of generating a page containing a large report. The server has to query the database for all required data and instantiate necessary data structures. Thousands of database records could create a very large object graph very quickly, thus consuming lots of memory. Next, the server must perform the required calculations or whatever data manipulation operations required to create the report. This means consuming CPU cycles and (usually) eating up more memory. Already, resource consumption in terms of IO, memory and processing power can clock in at high levels, even after significant optimization. After all this, the server then must render the markup to display the content which, in the case of many reports, means plenty of repetitive markup surrounding the stuff you spent all that time preparing.

In this case, why not just ship the data to the client and generate markup from a few templates in-browser? The more you can farm work out to clients, the fewer resources you have to consume on the server. This means less time your app spends in the HTTP request cycle and the sooner GC can run freeing memory, tempfile file handles can be closed and your app can begin relinquishing all resources, returning them back to the loving arms of the OS.

The same goes for bandwidth and transmission time (even gzip compression which you use currently, right!?) as, even next to large, JSON-serialized data, full-blown pages full of repetitive HTML tags appear huge by comparison. Which brings us to the next item: speed. (Yeah, I did mention the overlap, right?)

The sooner the server can ship the data, the sooner the browser can start rendering. The Google+ guys made it clear that when they do send markup, they frequently flush IO buffers to send ready-made chunks to the browser. This enables browsers to render sooner and begin fetching external resources like CSS, JS and images. With client-side rendering, shipping only data to the browser can get you the same effect. With proper incremental rendering, you render the content at the top of the report (a very good place to start) first thus showing the user some activity.

As another example, take ActiveRecord-powered form validation in Rails. The default behavior seen most commonly has, in cases of validation failure, the entire form being re-rendered and sent to the client.

Re-render the “new” action on validation failure
1
2
3
4
5
6
7
respond_to do |format|
  if @model.save
    format.html { redirect_to model_path(@model) }
  else
    format.html { render :action => :new, :status => :unprocessable_entity }
  end
end

However, as any moderately-experienced Rails dev knows, after failing validation, the ActiveRecord model makes available a hash of errors. Therefore, shipping only the error data offers a significant size reduction during transmission.

Only ship back the errors hash on validation failure
1
2
3
4
5
6
7
respond_to do |format|
  if @model.save
    format.json { render :json => @model }
  else
    format.json { render :json => @model.errors, :status => :unprocessable_entity }
  end
end

As for philosophy, different people have different views on moving business logic to the client side. Some business logic can move easily to the browser while other business logic can not or should not move. Twitter, for example, has made a point of becoming clients of their own API moving significant pieces of functionality to the browser. In our case of report rendering, why not move some of the calculations to the browser? Conversely, if a web app were a game, you might not want to move too much business logic to the browser if that might make it easier for players to cheat. Those who believe in client-side business logic will, by definition, have a much easier time accepting the idea of client-side rendering as well. For others, it may take a little more exploration for people to warm up to the idea.

Google has a reputation for measuring almost everything. Therefore, I imagine that they did not make the decision to implement client-side template rendering in Google+ simply for the lols. They have tremendous experience with all types of content and page fragments so should have copious performance data to look at.

Similarly, we (mere mortal developers) can learn from the ideas of measurement-influenced design decisions. Run some simulations to see which meets your performance requirements: rendering the page on the server and transmitting it to the browser or just sending the data and generating markup on the client. Right tool for the right job and different strokes for different folks. Or whatever.

Comments

Best Generic Erectile Dysfunction Pills Buy online Erectile Dysfunction pills Canada Buy Cialis 5/10/20 mg Buy Cialis 60mg online Buy Cialis online without prescription Buy cost Low Cialis Buy Cheap sale ED pills 10 mg Levitra