Amit
Amit

Reputation: 181

Highcharts low performance when adding yAxis dynamically

I am trying to add/delete yAxis dynamically but I observe performance issues. It takes more than a second (sometimes it goes upto 4 seconds) to dynamically add or remove a series into a new yAxis. I need to load end of day data (price point for each day) for 10 or more years in the chart.

Any advice in improving the performance will be much appreciated.

Few points to note -

  1. I can use different type of charts (line, ohlc, candlestick, area etc.)
  2. I need mouse tracking to be enabled as I am using click events on the series.
  3. User will have option to either choose to apply data grouping or to not.

Below is my code sample to illustrate the problem.

var chart;
var index = 2;

var groupingUnitsD = {units:[['day',[1]]], enabled:true};
var groupingUnitsWM = [[
        'week',                         // unit name
        [1]                             // allowed multiples
    ], [
        'month',
        [1, 2, 3, 4, 6]
    ]];
$(function () {
  var ohlc = [];
  
  $.getJSON('http://www.highcharts.com/samples/data/jsonp.php?filename=aapl-ohlcv.json&callback=?', function (data) {

    // split the data set into ohlc 
    var volume = [],
    dataLength = data.length,
    
    i = 0;

    for (i; i < dataLength; i++) {
      ohlc.push([
          data[i][0], // the date
          data[i][1], // open
          data[i][2], // high
          data[i][3], // low
          data[i][4] // close
      ]);
    }
    
    loadChart(data);
    });
    
    
    function loadChart(cdata){
      var highchartOptions = {
        plotOptions:{
          line: {
              enableMouseTracking: true,
              animation:false,
              marker: {
                  enabled: false
              }
          },
          series:{
        	  cursor: 'pointer',
          }
        },
        chart:{
          renderTo:'container'
        },
        navigator: {
          outlineColor: '#0066DD',
          outlineWidth: 1
        },
        xAxis: [{
        
        gridLineWidth: 1,
        gridLineColor: "#eaf5ff",
        lineColor: '#FF0000',
            lineWidth: 1
        }],
        yAxis:[{
          title:{
            text:"initial data"
          },
          id:'myaxis-1',
          height:'14%',
          top:'0%'
        }],

        series: [{
          data: cdata,
          turboThreshold:0,
          dataGrouping:groupingUnitsD
        }]
      };
      chart = new Highcharts.StockChart(highchartOptions);
    }
  
  
  
  
    $button = $('#button');
    $delButton = $('#delbutton');
    
    $button.click(function () {
          var axisObj = {
            title: {
                text: "axis-" + index,
            },
            id:'myaxis-'+ index
          };
      chart.addAxis(axisObj, false);
      console.log("Added axis:" + 'myaxis-'+ index);
      $('#axisList').append($('<option></option>').text('myaxis-'+ index));
      var seriesData = new Object();
      seriesData.name = 'axis-' + index;
      seriesData.id = 'myaxis-' + index;
      seriesData.yAxis = 'myaxis-'+ index;
      seriesData.data = ohlc;
      seriesData.type = 'line';
      seriesData.dataGrouping = groupingUnitsD;
      chart.addSeries(seriesData);
      updateAxisHeight();
      index++;
    });
    
    
  $delButton.click(function () {
  
    var $select = $('#axisList');
    console.log($select.val());
    console.log(chart.get($select.val()));
    var selId = $select.val();
    
    chart.get(selId).remove();
     $('option:selected', $select).remove();
    var i=0;
    updateAxisHeight();
  });
  
  updateAxisHeight = function(){
  
    var i=0;
    $("#axisList > option").each(function() {
        chart.get(this.value).update({ height: '14%',top: (i*15) + '%',offset:0 });
        i++;
    });
  }
  
  
  

});
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
    <script src="http://code.highcharts.com/stock/highstock.js"></script>
    <script src="http://code.highcharts.com/stock/highcharts-more.js"></script>
    <script src="http://code.highcharts.com/modules/exporting.js"></script>

<button id="button" class="autocompare">Add yAxis</button><br>
<!--Entrt yAxis index to delete:<input type='text' id="delAxis"/> -->

<select id="axisList" name="axisList">
  <option value="myaxis-1" selected="selected">myaxis-1</option>
</select>


<button id="delbutton" class="autocompare">Delete yAxis</button>
<div id="container" style="height: 800px"></div>

Upvotes: 2

Views: 367

Answers (1)

Vicky Chijwani
Vicky Chijwani

Reputation: 10479

You can significantly improve the performance in this case with one trick: when performing several consecutive operations that each require a redraw (add series, add axis, update axis height), don't redraw until you've told Highcharts about all the operations.

On my machine, this improves the performance of your add axis function by 5x-6x. See code and comments below.

var chart;
var index = 2;

var groupingUnitsD = {units:[['day',[1]]], enabled:true};
var groupingUnitsWM = [[
        'week',                         // unit name
        [1]                             // allowed multiples
    ], [
        'month',
        [1, 2, 3, 4, 6]
    ]];

$(function () {
  var ohlc = [];
  
  $.getJSON('http://www.highcharts.com/samples/data/jsonp.php?filename=aapl-ohlcv.json&callback=?', function (data) {

    // split the data set into ohlc 
    var volume = [],
    dataLength = data.length,
    
    i = 0;

    for (i; i < dataLength; i++) {
      ohlc.push([
          data[i][0], // the date
          data[i][1], // open
          data[i][2], // high
          data[i][3], // low
          data[i][4] // close
      ]);
    }
    
    loadChart(data);
    });
    
    
    function loadChart(cdata){
      console.time("chart load");
      var highchartOptions = {
        plotOptions:{
          line: {
              enableMouseTracking: true,
              animation: false,
              marker: {
                  enabled: false
              }
          },
          series:{
        	  cursor: 'pointer',
          }
        },
        chart:{
          alignTicks: false,
          events: {
            load: function () {
              console.timeEnd("chart load");
            }
          },
          renderTo:'container'
        },
        yAxis:[{
          title:{
            text:"initial data"
          },
          id:'myaxis-1',
          height:'14%',
          top:'0%'
        }],

        series: [{
          data: cdata,
          turboThreshold:0,
          dataGrouping:groupingUnitsD
        }]
      };
      chart = new Highcharts.StockChart(highchartOptions);
    }
  
  
  
  
    $button = $('#button');
    $delButton = $('#delbutton');
    
    $button.click(function () {
      var startTime = new Date().getTime();
          var axisObj = {
            title: {
                text: "axis-" + index,
            },
            id:'myaxis-'+ index
          };
      chart.addAxis(axisObj, false, false);    // don't redraw yet
      console.log("Added axis:" + 'myaxis-'+ index);
      $('#axisList').append($('<option></option>').text('myaxis-'+ index));
      var seriesData = new Object();
      seriesData.name = 'axis-' + index;
      seriesData.id = 'myaxis-' + index;
      seriesData.yAxis = 'myaxis-'+ index;
      seriesData.data = ohlc;
      seriesData.type = 'line';
      seriesData.dataGrouping = groupingUnitsD;
      chart.addSeries(seriesData, false);      // don't redraw yet
      updateAxisHeight(false);                 // don't redraw yet
      index++;

      // finally, redraw now
      chart.redraw();

      var endTime = new Date().getTime();
      console.log("add axis took " + (endTime - startTime) + " msec");
    });
    
    
  $delButton.click(function () {
  
    var $select = $('#axisList');
    console.log($select.val());
    console.log(chart.get($select.val()));
    var selId = $select.val();
    
    chart.get(selId).remove();
     $('option:selected', $select).remove();
    var i=0;
    updateAxisHeight();
  });
  
  updateAxisHeight = function(redraw){
    // set redraw to true by default, like Highcharts does
    if (typeof redraw === 'undefined') {
      redraw = true;
    }
  
    var i=0;
    $("#axisList > option").each(function() {
        // don't redraw in every iteration
        chart.get(this.value).update({ height: '14%',top: (i*15) + '%',offset:0 }, false);
        i++;
    });

    // redraw if caller asked to, or if the redraw parameter was not specified
    if (redraw) {
      chart.redraw();
    }
  }
  
  
  

});
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
    <script src="http://code.highcharts.com/stock/highstock.js"></script>
    <script src="http://code.highcharts.com/stock/highcharts-more.js"></script>
    <script src="http://code.highcharts.com/modules/exporting.js"></script>

<button id="button" class="autocompare">Add yAxis</button><br>
<!--Entrt yAxis index to delete:<input type='text' id="delAxis"/> -->

<select id="axisList" name="axisList">
  <option value="myaxis-1" selected="selected">myaxis-1</option>
</select>


<button id="delbutton" class="autocompare">Delete yAxis</button>
<div id="container" style="height: 800px"></div>

Upvotes: 0

Related Questions