Quantcast
Channel: Pedro Alves on Business Intelligence
Viewing all articles
Browse latest Browse all 186

Making CDF calls asynchronous

$
0
0

Motivation

Since the beginning, CDF has always worked in sync mode. Really not sure if it was a decision based on simplification or simply lack of skill. It's time to change that, though.

Having CDF components making synchronous requests simplifies the lifecycle. However, has a performance penalty, like the image shows:


 We can very easily get into a big number of components. 6 selects, 3 charts and a table add up to 10 requests. In the synchronous world, means that we will only make one request after getting the answer back. In asynchronous mode, all requests are done at the same time* and then the dashboard will render much, much faster. There's also another problem; some browsers lock some of it's functionality while the request is being made. In Firefox, for instance, you can't even change tabs. That's bad.

 CDF and CDE have tons of very important performance tweaks. All files are minimized and concatenated into one, all caching information is built so that as little requests are made and CDA has a very strong query cache layer, optionally backed up by CDC. Turning the lifecycle into asynchronous is the next step

Challenges

This is a big change, hopefully only for the CDF core and not for end users. Basically, in async mode, the concept of "postExecution" changes; Instead of being executed after the component executes itself, has to be called after the component renders itself. So all components will have to be changed, one by one, to conform to the new lifecycle to be implemented.

Currently all components inherit from BaseComponent. That's where the core lifecycle is. Now we're implementing a new one, called UnmanagedComponent.

We're not converting all the components now. It would be a very big effort. It's something that will happen over time. Our focus right now are the following ones:
  • Selectors
  • CCC Charts
  • Query component
  • Table component
This should give us a good performance boost to start with.

All this work is being developed as we speak, and you can follow the progress by monitoring the async github branch, .

Examples


Here are some samples of the old and new way of implementing components. This is the classic way of displaying a Hello World component

HelloBaseComponent = BaseComponent.extend({
update: function() {
$("#" + this.htmlObject).text("Hello World!");
}
});

This is on the new, and soon to be recommended approach:
HelloUnmanagedComponent = UnmanagedComponent.extend({
update: function() {
var render = _.bind(this.render, this);
this.synchronous(render);
},

render: function() {
$("#" + this.htmlObject).text("Hello World!");
}
});
This may not seem a big gain. However, if we need data from datasources, it's much easier to use:
HelloQueryBaseComponent = BaseComponent.extend({
update: function() {
var myself = this;
var query = new Query(myself.queryDefinition);
query.fetchData(myself.parameters, function(values) {
var changedValues = undefined;
if((typeof(myself.postFetch)=='function')){
changedValues = myself.postFetch(values);
}
if (changedValues !== undefined) {
values = changedValues;
}
myself.render(values);
});
},

render: function(data) {
$("#" + this.htmlObject).text(JSON.stringify(data));
}
});


In the new format, you'll just have to call the triggerQuery method
HelloQueryUnmanagedComponent = UnmanagedComponent.extend({
update: function() {
var render = _.bind(this.render,this);
this.triggerQuery(this.queryDefinition, render);
},

render: function(data) {
$("#" + this.htmlObject).text(JSON.stringify(data));
}
});


Besides triggerQuery there are other useful calls: triggerAjax and synchronous, the first one for standard ajax calls and the second for synchronized calls, like used in the first example


*Caveat

I wrote that "In asynchronous mode, all requests are done at the same time". That's not exactly true as browsers limit the amount of concurrent requests. Depends on the browser, but it's something around 4 simultaneous requests. If we have 10 components, the requests will still be split into 2 or 3 batches.

Just to let you know that we're also thinking about this, but that's for another blog post ;)

Viewing all articles
Browse latest Browse all 186

Trending Articles