Alex Neth
Alex Neth

Reputation: 3336

Highcharts heatmap chart labels render extremely slow

I'm using Highcharts to generate a heatmap grid with around 10k grid cells. The heatmap renders in under a second without dataLabels. However if I enable dataLabels, which are necessary for my project, the same heatmap takes 10 seconds to render. I tried setting useHTML to true, and that renders in 30+ seconds. I'm not doing any work within the dataLabel rendering. Is there any way to speed this up?

Image of part of grid - my grid is 270 rows

Upvotes: 0

Views: 1375

Answers (1)

morganfree
morganfree

Reputation: 12472

The example with 10k cells in the heatmap with enabled data labels is here.

Highcharts.chart('container', {
  chart: {
    type: 'heatmap'
  },

  xAxis: {
    min: 0,
    max: 99
  },

  series: [{
    data: data,
    dataLabels: {
      enabled: true
    }
  }]
});
  1. No-opt rendering time: 33.5 s

Profiling heatmap

From the profiler I can say thet there are two good candidates for optimization.

  1. Rendering with overlapping labels: 10.4 s

    dataLabels: {
      enabled: true,
      allowOverlap: true
    }
    
  2. No textOutline: 8.56 s

    dataLabels: {
      enabled: true,
      allowOverlap: true,
      shadow: false,
      style: {
        textOutline: null,
        color: 'black'
      }
    },
    

The other candidate is about setting zIndex for the data labels, I cannot see how to optimize it without changing internal Highcharts method responsible for drawing data labels. You can wrap drawDataLabels method and remove the part for setting label's zIndex.

  1. Without zIndex: 1.62 s

    attr = {
      //align: align,
    
      fill: options.backgroundColor,
      stroke: options.borderColor,
      'stroke-width': options.borderWidth,
    
      r: options.borderRadius || 0,
      rotation: rotation,
      padding: options.padding
      //    zIndex: 1 /* commenting this part gives a few good seconds */
    };
    

full example: http://jsfiddle.net/dddqrb9f/1/

I commented only one line in the function but you can remove additional features if you don't need them - e.g. if you don't need labels, you can render text only.

  if (!dataLabel) {
      dataLabel = point.dataLabel = renderer['text']
  1. Text instead of labels: 0.864 s

example: http://jsfiddle.net/dddqrb9f/2/

Upvotes: 2

Related Questions