Tag Archives: wpo

How to avoid 26 API requests on your page?

The problem

Create an applications relying on web APIs seems to be quite popular these days. There is already an impressive collection of ready-to-use public APIs (check it at http://www.programmableweb.com ) that we can consume to create mashup, or add features into our web sites.

In the meantime, it has never been so easy to create your own REST-like API with node.js, asp.net web api, ruby or whatever tech you want. It’s also very common to create your own private/restricted API for your SPA, Cross-platform mobiles apps or your own IoT device. The naïve approach, when building our web API, is to add one API method for every feature ; at the end, we got a well-architectured and brilliant web API following the Separation of Concerns principle : one method for each feature. Let’s put it all together in your client … it’s a drama in terms of web performance for the end user and there is never less than 100s requests/sec  on staging environment; Look at your page, there are 26 API calls on your home page !

I talk here about web apps but it’s pretty the same for mobile native applications .RTT and latency is much more important than bandwidth speed. It’s impossible to create a responsive and efficient application with a chatty web API.

The proper approach

At the beginning of December 2014, I attended at the third edition in APIdays in Paris. There was an interesting session –among the others- on Scenario Driven Design by @ijansch.

The fundamental concept in any RESTful API is the resource. It’s an abstract concept and it’s merely different from a data resource. A resource should not be a raw data model (the result of an SQL query for the Web) but should be defined with client usage in mind. “REST is not an excuse to expose your raw data model. “ With this kind of approach, you will create dump clients and smart APIs with a thick business logic.

A common myth is “Ok, but we don’t know how our API is consumed, that’s why we expose raw data”. Most of the times, it’s false. Let’s take the example of twitter timelines. They are list of tweets or messages displayed in the order in which they were sent, with the most recent on top. This is a very common feature and you can see timelines in every twitter client. Twitter exposes a timeline API and API clients just have to call this API to get timelines. Especially, clients don’t have to compute timelines by themselves, by requesting XX times the twitter API for friends, tweets of friends, etc …

I think this is an important idea to keep in mind when designing our APIS. generally,  We don’t need to be so RESTful (Wwhat about HATEOS ?). Think more about API usability and scenarios, that RESTfullness.

The slides of this session are available here.

Another not-so-new approach: Batch requests

Reducing the number of request from a client is a common and well-known Web Performance Optimization technique. Instead of several small images, it’s better to use sprites. Instead of many js library files, it’s better to combine them. Instead of several API calls, we can use batch requests.

Batch requests are not REST-compliant, but we already know that we should sometimes break the rules to have better performance and better scaliblity.

If you find yourself in need of a batch operation, then most likely you just haven’t defined enough resources., Roy T. Fieldin, Father of REST

What is a batch request ?

A batch request contains several different API requests into a single POST request. HTTP provides a special content type for this kind of scenario: Multipart. On server-side, requests are unpacked and dispatched to the appropriate API methods. All responses are packed together and sent back to the client as a single HTTP response.

Here is an example of a batch request:

Request

POST http://localhost:9000/api/batch HTTP/1.1
Content-Type: multipart/mixed; boundary="1418988512147"
Content-Length: 361

--1418988512147
Content-Type: application/http; msgtype=request

GET /get1 HTTP/1.1
Host: localhost:9000


--1418988512147
Content-Type: application/http; msgtype=request

GET /get2 HTTP/1.1
Host: localhost:9000


--1418988512147
Content-Type: application/http; msgtype=request

GET /get3 HTTP/1.1
Host: localhost:9000


--1418988512147--

Response

HTTP/1.1 200 OK
Content-Length: 561
Content-Type: multipart/mixed; boundary="91b1788f-6aec-44a9-a04f-84a687b9d180"
Server: Microsoft-HTTPAPI/2.0
Date: Fri, 19 Dec 2014 11:28:35 GMT

--91b1788f-6aec-44a9-a04f-84a687b9d180
Content-Type: application/http; msgtype=response

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

"I am Get1 !"
--91b1788f-6aec-44a9-a04f-84a687b9d180
Content-Type: application/http; msgtype=response

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

"I am Get2 !"
--91b1788f-6aec-44a9-a04f-84a687b9d180
Content-Type: application/http; msgtype=response

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

"I am Get3 !"
--91b1788f-6aec-44a9-a04f-84a687b9d180--

Batch requests are already supported by many web Frameworks and allowed by many API providers:  Asp.net web api, a node.js module, Google Cloud platform, Facebook, Stackoverflow,Twitter …

Batch support in  asp.net web api

To support batch requests in your asp.net web API, you just have to add a new custom route  :

config.Routes.MapHttpBatchRoute(
routeName: "batch",
routeTemplate: "api/batch",
batchHandler: new DefaultHttpBatchHandler(GlobalConfiguration.DefaultServer)
);

Tip : the DefaultBatchHandler doesn’t provide a way to limit the number of requests in a batch. To avoid performance issues, we may want to limit to 100/1000/… concurrent requests. You have to create your own implementation by inheriting DefaultHttpBatchHandler.

This new endpoint will allow client to send batch requests and you have nothing else to do on server-side. On client side,  to send batch requests, you can use this jquery.batch, batchjs, angular-http-batcher module, …

I will not explain all details here but there is an interesting feature provided by DefaultHttpBatchHandler : the property ExecutionOrder allow to choose between sequential or no sequential processing order. Thanks to the TAP programming model, it’s possible to execute API requests in parallel (for true async API methods)

Here is the result of async/sync batch requests for a pack of three 3 web methods taking one second to be processed.

batch

Finally, Batch requests are not a must-have feature but it’s certainly something to keep in mind. It can help a lot in some situations. A very simple demo application is available here. Run this console app or try to browse localhost:9000/index.html. From my point of view here are some Pros/Cons of this approach.

Pros Cons
Better client performance (less calls) May increase complexity of client code
Really easy to implement on server side Hide real clients scenarios, not REST compliant
Parallel requests processing on server side Should limit batch size at server level for public API
Allow to use GET, POST, PUT, DELETE, … Browser cache may not work properly

How speedy.js is your web site ?

As a performance officer, I recently watch by a presentation from Lara Callender Swanson about how Etsy moved towards a culture of performance and mobile web by educating, incentivizing and empowering everyone who works at Etsy.

Inspired by a repo on github and StackExchange‘s Miniprofiler, I’ve created to very simple script to display Navigation Timing stats at the top of a web page.

Navigation Timing is a JavaScript API for accurately measuring performance on the web. The API provides a simple way to get accurate and detailed timing statistics—natively—for page navigation and load events. It has always been a small challenge to measure  the time it takes to fully load a page, but Navigation Timing API now make this easy for all of us.

It’s important to understand that Navigation Timing data is very similar to network stats in developer tools.

speedy.js

Can I use … ?

Navigation Timing API is now supported by all major browsers (Can I use …?). Google Analytics and RUM services use it since a long time ago.  In case, it’s not supported by your browser an error message will be displayed.

nospeedy.js

No message => don’t hesitate to create an issue on github

Mobile ready ?

This is maybe the most interesting part. Developer tools are not available on mobile/tablet version so you don’t have any chance to evaluate page load time and to explain why it may be slow.

On production ?

Of course, it’s not recommended to display this kind of data to your users, but you may find several ways to use it on production. There are browser extensions to inject custom javascripts into any website (Cjs, Greasemonkey) ; Fiddler allows you to automatically inject scripts into a page (stackoverflow)

Here is an example on my stackoverflow profile

speedyonso

To conclude, don’t forget that Performance is a feature ! Displaying page load time on each page and to everyone is a great chance to detect performance issues early. Does a page violate your SLA? I think it’s now a little easier with this script.

Do you use {pretty print} ?

Steve Souders began to describe Web Performance Optimization 10 years ago. WPO is the field of knowledge about increasing the speed in which web pages are downloaded and displayed on the user’s web browser. He wrote and contributed to many books (High Performance Web Sites , Even Faster Web Sites , Web Performance Daybook V2
) to explain us his best practices for performance along with the research and real-world results behind them.

One of the most important rules is to Combine & Minify resources. Bundling combines multiples files into a single file whereas Minification is the process of removing all unnecessary characters from source code without changing its functionality.

With the latest HTML5 specification and the emergence of JS frontend frameworks like JQuery and more recently AngularJS, JavaScript has never been so used and so popular. We can now create scalable, maintainable applications, unified under a single language: JavaScript !

As we’re all good web citizen, all our resources (JS/CSS) are bundled and minified on production. This is sometimes where things start going bad. Have you ever try to debug JavaScript on production? The primary drawback of this optimization is that it makes debugging your JavaScript code a nightmare, since the browser’s developer tools will show you code that is virtually unreadable.

For example, a production JavaScript may looks like this: 14K characters on the same line.

min

It’s impossible to debug the previous script because browsers can’t set breakpoint at character level (only at line-level).

Helpfully, some of the browsers have an option in developers tools to un-minify partially a JavaScript file. This option is called “pretty print” and the icon is like {}.

Chrome
chrome

Internet Explorer
,ie

In Firefox (since December 2013)
firefox

Here is the result after pretty print.

unmin

It’s fairly better and you have the nearly the same debugging experience that for dev scripts. Sometimes it’s not enough because JavaScript minification tools rename local functions & variables. It’s common to see a(), b(), c() in a minified script.  A good indentation won’t change this.

Fortunately, Source Maps provide a way of mapping the lines & columns of the production source code (bundled & minified), back to their original locations in the corresponding uncompressed source files. This feature is supported by all modern browsers.

An additional file is generated during the minification process and is added at the top of the optimized file.

map

Source Maps are easily generated by grunt-contrib-uglify or Closure Compiler. Unfortunately, it’s still not supported by Microsoft ASP.NET Web Optimization Framework. For sure, this is something that needs to be done. Web Essentials also offer this feature.

It’s a nice tip for every web developer but the good question may be : Why do you have to debug production code ?