Reputation: 549
I have a page with 2 highCharts on and wondered if there was a way to speed up the load times for the charts. The first is the main chart with 2 series and the second, is more of a ‘thumbnail’ chart and has 4 series.
I populate a listbox with a list of dates and as the user selects each date I make an ajax call to get some data.
I build my charts like in a constructor like this …
basicMaxChart = function() {
options = {
chart: {},
/*missed for brevity*/,
series: [{},{}]
}; // options
return options;
}; // Max
basicMiniChart = function() {
optionsMini = {
chart: {},
/*missed for brevity*/,
series: [{},{},{},{}]
}; // optionsMini
return optionsMini;
}; // Mini
My document ready function,
// Globals
var options;
var optionsMini;
var chart;
var chartMini;
jQuery("document").ready(function() {
function createChart() {
options = $.extend({}, basicMaxChart options);
chart = new Highcharts.Chart(options);
};
function createMiniChart() {
optionsMini = $.extend({}, basicMiniChart(), optionsMini);
chartMini = new Highcharts.Chart(optionsMini);
};
// create some empty charts for place holders
createChart();
createMiniChart();
function loadData(){
// missed for brevity, but declare some vars and get some values from inputs
var aLen = document.getElementById("someInput").value;
var d1 ...
var data = {
compareD1 : d1,
m1 : m1,
someVal : aLen
};
$.post("getSomeData.php", data, function(json) {
/* Clearing the series first or ‘Destroying’ the chart only only serves to make things worse …
if (typeof chartMini != 'undefined') {
while(chartMini.series.length > 0)
chartMini.series[0].remove();
//chartMini.destroy();
}
*/
options.series[0] = json[0];
options.series[1] = json[1];
optionsMini.series[0] = json[3];
optionsMini.series[1] = json[4];
optionsMini.series[2] = json[5];
optionsMini.series[3] = json[6];
chart = new Highcharts.Chart(options);
chartMini = new Highcharts.Chart(optionsMini);
chart.series[0].options.color = 'blue';
chart.series[0].update(chart.series[0].options);
chart.series[1].options.color = 'red';
chart.series[1].update(chart.series[1].options);
chartMini.series[0].options.color = '#A9CBE9';
….
….
chartMini.series[3].update(chartMini.series[3].options);
}, "json");
}); // ready
The loadData function makes an ajax call and returns a json object containing data for both charts within about 500ms. (I'm happy with the speed of the getSomeData.php script).
If I remove everything related to chartMini / optionsMini from the loadData function, the main chart loads really quickly too. But as soon as I throw the ‘Mini’ back in the things slow down and neither charts displays for about 5 seconds (In fact I often get a 'Not Responding message in FireFox'). Each ‘Data’ element in my json object has 700 data points (I didn’t think that was particularly large).
I take it that my inexperience with highcharts is the cause of the slowness. May I ask if you have any suggestions on how I might improve the performance of the build / load times for the two charts.
Thanks for reading.
Upvotes: 3
Views: 5141
Reputation: 20536
From the code you've displayed the costly part is after you've created your chart, but continue to update it. Every update
method call you make will force a redraw
, which is very resource demanding.
Ideally you finish up all of your options in advance of creating the chart. This slightly depends on your JSON to make it correct, but imagine something like this:
options.series[0] = json[0];
options.series[0].options.color = 'blue';
options.series[1] = json[1];
options.series[1].options.color = 'red';
optionsMini.series[0] = json[3];
optionsMini.series[0].options.color = '#A9CBE9';
// ...
chart = new Highcharts.Chart(options);
chartMini = new Highcharts.Chart(optionsMini);
You may have to create the options
object if it does not already exist in your JSON.
The alternative lazy variation of this is to just postpone the redraw
in your current code, and then do one manual redraw
after it. Imagine this:
chart = new Highcharts.Chart(options);
chartMini = new Highcharts.Chart(optionsMini);
chart.series[0].options.color = 'blue';
chart.series[0].update(chart.series[0].options, false); // false to prevent redraw
chart.series[1].options.color = 'red';
chart.series[1].update(chart.series[1].options, false); // false to prevent redraw
chartMini.series[0].options.color = '#A9CBE9';
chartMini.series[0].update(chartMini.series[0].options, false); // false to prevent redraw
// ...
chart.redraw(); // force redraw after all changes are made
chartMini.redraw(); // force redraw after all changes are made
Note that this is slower than the first approach as it requires updating lots of data in the series several times and also doing one redraw
of each chart which will not happen with the first approach.
Upvotes: 3