Performance comparison on Programming Models

Now the OpenSocial spec has provided multiple ways for gadget developer to write gadgets. This short article tries to give a quick overview and performance comparison between each of the method. We divide the comparison into 2 parts: a) rendering performance and b) data requesting performance.

Rendering Performance

Traditional model

This model is introduced in the very early stage of OpenSocial (the internal version v0.6), and it's still being used in various gadgets.

In this model, the container fetches gadget spec which is XML format from application server, renders it into HTML page, and send it back to user's client. When client parsing the HTML, social data requests are triggered automatically and they are sent back to container via JavaScript API calls. Since this gadget is hosted on container's server, gadget is not able to issue direct AJAX requests to their home server due to the same-domain restriction. Therefore, all "cross-domain" application data requests are sent through gadget.io.makeRequest calls and the container acts like a proxy to help fetching the data from remote sites.

It's obvious that the process is not that efficient: 3 requests have been triggered by client, and there're totally 5 HTTP round-trips involved for rendering simple 1 gadget. Moreover, its data requesting, which issued through gadget.io.makeRequest calls is not efficient either. We'll discuss it in the a:Data Requesting Performance section.

Proxied Content + Data Pipelining

As one of the major improvements introduced in OpenSocial 0.9, Proxied Content + Data Pipelining is a big step addressing the performance issue in previous OpenSocial versions.

According to the figure, as container fetched the gadget spec and identified the gadget content view to be rendered and displayed is Proxied Content, it sends back the gadget content request to application server with the social data which developer claimed in the gadget spec. In most of the cases, this request is signed with the method roughly the same as gadget.io.makeRequest, indicated by the attribute authz. The key magic here are the direction of social data transmission and the place where rendering happens.

  • Rather than fetching the social data*after* displaying rendered gadget on the client's screen, which traditional model does, container pushes the required social data to application server before the rendering stage. Therefore the un-necessary social data requesting/responding round-trip is eliminated.
  • The gadget rendering process happens on the application side, rather than on the container. This change, comparing to the traditional one, offers extra flexibility to the developer to represent maybe totally different content to specific user. Moreover, since the required social data has been pushed in the step 4, the application data associated with the specific user could be identified in the rendering stage thus no need to be transfered in some separated round-trips.

Yet another big advantage of this approach is the utilizing of Data Pipeline. It's not simply a content caching model but a revolutionary programming pattern. We'll discuss it in the a:following section.

Template + OpenSocial Markup Language + AppData Pushing

Like Proxied Content, Template + OpenSocial Markup Language is also introduced in OpenSocial 0.9. There's continues demanding for a templating language by the developer community to simplify the gadget implementation. As a side effect (maybe), this new comer also improves the rendering performance a lot:

  • In the server side rendering stage which happens on the container, the social data is filled into the pre-defined template, thus no social data transmission is conducted;
  • Template + OSML is often used together with AppData pushing technique. Before rendering, the user-associated application data is off-line pushed to container by application server. Therefore, no application data transmission is conducted in gadget's first rendering, either.

Given the gadget spec, which contains pre-defined template, could be cached on the container side, the whole rendering could even be processed with zero application server hit! It's so efficient that it's some containers' only supported rendering model on the user's profile page.

Delegated Content (iframe model in extension proposal)

The Delegated Content model is our new proposed one for extension and hopes it could be adopted in the next version of OpenSocial standard. The main point differentiate it with previous methods is, the gadget content page is hosted on the application server, rather than on container. In other words, the source of this iframed page points to application server. This same-domain behavior brings many benefits including:

  • Easy cookie sharing;
  • Convenient direct AJAX data requesting;
  • Secure data transmission if it's rightly implemented, etc.

Moreover, since now the gadget content page looks pretty like the stand-alone web page, it's not just decouple the dependency between container and application server in the developing stage, but also simplified the application migration from other platforms to OpenSocial.

Despites the above standard way, a well adopted home-made workaround by the developer community is the variant of Proxied Content + Data pipelining model, as shown in the above diagram.

The gadget spec guides the container pushing demanded social data to the application server, generates a dummy content page containing redirection code, and sends back the dummy page along with a session key, which is used to validate the future coming page request and access the cached social data.

However, the potential performance issues lurking under the above models should be carefully considered before implementing. Since the gadget running on iframe mode is totally out of container's control, the container-side optimizations, like CDN, content rewriting, and caching won't bless the gadget any more. Which is even worse, all data request will flood the application server directly and the traffic will be huge!

  • Normally with proxied content (and/or data-pipelining, but the developer could also use REST if they wanted of course) there's a good bit of caching going on, and re-fetching is only done on new users or when the back-end decided to do a cache-invalidate call. So the gadget developer's servers wouldn't see much traffic at all.
  • If however the iframe points to their server (and knowing the average web developer's they'll probably use a pragma:no-cache), every profile/home/canvas view with their application generates a hit to their back-end. If that's a popular application on a large, say, Chinese container, well that could be enough traffic to melt most simple hosting setups, and dealing with such traffic is a skill-set on it's own.

Therefore, please think twice and implement it very carefully if you're really about to use this model.

Data Requesting Performance

More information please refer to Remote Data Requests (v0.9)).

Traditional gadget.io.makeRequest (OpenSocial spec version 0.7, 0.8) / osapi.http (0.9+)

It's the traditional model introduced in the very early stage of OpenSocial (the internal version v0.6), and it's still being used in various gadgets.

Due to the cross-domain constrain, all data requests issued from client to remote sites, no matter whether its content is JSON data or static images, should go through the container. It puts in-neglectable burden to container and the ad-hoc caching policy is not quite efficient, either.

Data Pipelining + Invalidation

AppData Pushing

Direct AJAX