Chart.js too slow rendering vertical stacked bars chart

I'm using chart.js API to render a several stacked vertical bars chart, but the performance is slow. I even made some changes such that all the content object was already processed by the server, and not the browser, but I realised the big majority of time comes from the final function new Chart(overallStatsChart, content);.

I also tried switching off animation, which slightly improved performance, but not that much.

Any ideas on how to improve performance, that is, initial loading?

var countryList = {"AR":"Argentina","AU":"Australia","BO":"Bolivia","BR":"Brasil","CA":"Canada","CL":"Chile","CN":"中国","CO":"Colombia","CR":"Costa Rica","CU":"Cuba","CZ":"Česká","DE":"Deutschland","DK":"Danmark","DO":"Rep. Dominicana","EC":"Ecuador","ES":"España","FI":"Suomessa","FR":"France","GR":"Ελλάδα","GT":"Guatemala","HU":"Magyarország","IE":"Ireland","IN":"India","IT":"Italia","JP":"日本","MX":"México","NI":"Nicaragua","NL":"Nederland","NO":"Norge","PA":"Panamá","PE":"Perú","PL":"Polska","PR":"Puerto Rico","PT":"Portugal","PY":"Paraguay","RO":"România","RU":"Россия","SE":"Sverige","SV":"El Salvador","TR":"Türkiye","UA":"Україна","UK":"United Kingdom","US":"USA","UY":"Uruguay","VE":"Venezuela"};

//populates country labels
var labels = [], size = 0;
for (var key in countryList){
    labels.push(key);
    size++;
}

var _data = function(i){
    var arr = [];
    for (var n=0; n<size; n++){
        arr.push(n==i ? 1 : 0);
    }            
    return arr;
};

var dataset = [], i=0;
for (var key in countryList){

    dataset.push(
        {
            label: "depreciation",
            data: _data(i),
            backgroundColor: 'navy'
        }, {
            label: "insurance",
            data: _data(i),
            backgroundColor: 'blue'
        }, {
            label: "credit",
            data: _data(i),
            backgroundColor: 'aqua'
        }, {
            label: "inspection",
            data: _data(i),
            backgroundColor: 'teal'
        }, {
            label: "road taxes",
            data: _data(i),
            backgroundColor: 'olive'
        }, {
            label: "maintenance",
            data: _data(i),
            backgroundColor: 'green'
        }, {
            label: "repairs",
            data: _data(i),
            backgroundColor: 'lime'
        }, {
            label: "fuel",
            data: _data(i),
            backgroundColor: 'maroon'
        }, {
            label: "parking",
            data: _data(i),
            backgroundColor: 'yellow'
        }, {
            label: "tolls",
            data: _data(i),
            backgroundColor: 'orange'
        }, {
            label: "fines",
            data: _data(i),
            backgroundColor: 'red'
        }, {
            label: "washing",
            data: _data(i),
            backgroundColor: 'purple'
        }, {
            label: "maintenance",
            data: _data(i),
            backgroundColor: 'green'
        }
    );

    i++;
}                          

var options = {
    maintainAspectRatio: false,
    legend: {
        position: 'bottom', // place legend on the right side of chart
        display: false, //do not display
        labels : {
            fontSize: 9,
            fontColor: 'black'
        }
    },
    scales: {
        xAxes: [{
            stacked: true, // this should be set to make the bars stacked
            beginAtZero: true
        }],
        yAxes: [{
            stacked: true, // this also..
            beginAtZero: true
        }]
    },
    animation: {
        duration : 1000,
        easing : 'linear'
    }
};

var content = {
    type: 'bar',
    data: {
        labels: labels,
        datasets: dataset
    },
    options: options
}; 

//I made tests with timestamps and here it takes the biggest part of the time
new Chart(overallStatsChart, content);
.chart {
    position: relative;
    margin: auto;
}
#overallStatsChartDiv{
    min-height: 500px;
} 
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<div class="chart" id="overallStatsChartDiv">
    <canvas id="overallStatsChart"></canvas>
</div>

Upvotes: 0

Views: 2958

Answers (1)

Now I get it :) I was wrongly duplicating the data attributes, based on this answer.

Solution is quite simple, every data attribute can have directly all the values, without the need of introduction of zeros.

var countryList = {"AR":"Argentina","AU":"Australia","BO":"Bolivia","BR":"Brasil","CA":"Canada","CL":"Chile","CN":"中国","CO":"Colombia","CR":"Costa Rica","CU":"Cuba","CZ":"Česká","DE":"Deutschland","DK":"Danmark","DO":"Rep. Dominicana","EC":"Ecuador","ES":"España","FI":"Suomessa","FR":"France","GR":"Ελλάδα","GT":"Guatemala","HU":"Magyarország","IE":"Ireland","IN":"India","IT":"Italia","JP":"日本","MX":"México","NI":"Nicaragua","NL":"Nederland","NO":"Norge","PA":"Panamá","PE":"Perú","PL":"Polska","PR":"Puerto Rico","PT":"Portugal","PY":"Paraguay","RO":"România","RU":"Россия","SE":"Sverige","SV":"El Salvador","TR":"Türkiye","UA":"Україна","UK":"United Kingdom","US":"USA","UY":"Uruguay","VE":"Venezuela"};

//populates country labels
var labels = [], size = 0;
for (var key in countryList){
    labels.push(key);
    size++;
}

var _data = function(){
    var arr = [];
    for (var n=0; n<size; n++){
        arr.push(1);
    }            
    return arr;
};


var dataset = [
    {
        label: "depreciation",
        data: _data(),
        backgroundColor: 'navy'
    }, {
        label: "insurance",
        data: _data(),
        backgroundColor: 'blue'
    }, {
        label: "credit",
        data: _data(),
        backgroundColor: 'aqua'
    }, {
        label: "inspection",
        data: _data(),
        backgroundColor: 'teal'
    }, {
        label: "road taxes",
        data: _data(),
        backgroundColor: 'olive'
    }, {
        label: "maintenance",
        data: _data(),
        backgroundColor: 'green'
    }, {
        label: "repairs",
        data: _data(),
        backgroundColor: 'lime'
    }, {
        label: "fuel",
        data: _data(),
        backgroundColor: 'maroon'
    }, {
        label: "parking",
        data: _data(),
        backgroundColor: 'yellow'
    }, {
        label: "tolls",
        data: _data(),
        backgroundColor: 'orange'
    }, {
        label: "fines",
        data: _data(),
        backgroundColor: 'red'
    }, {
        label: "washing",
        data: _data(),
        backgroundColor: 'purple'
    }, {
        label: "maintenance",
        data: _data(),
        backgroundColor: 'green'
    }
];                      

var options = {
    maintainAspectRatio: false,
    legend: {
        position: 'bottom', // place legend on the right side of chart
        display: false, //do not display
        labels : {
            fontSize: 9,
            fontColor: 'black'
        }
    },
    scales: {
        xAxes: [{
            stacked: true, // this should be set to make the bars stacked
            beginAtZero: true
        }],
        yAxes: [{
            stacked: true, // this also..
            beginAtZero: true
        }]
    },
    animation: {
        duration : 1000,
        easing : 'linear'
    }
};

var content = {
    type: 'bar',
    data: {
        labels: labels,
        datasets: dataset
    },
    options: options
}; 

//I made tests with timestamps and here it takes the biggest part of the time
new Chart(overallStatsChart, content);
.chart {
    position: relative;
    margin: auto;
}
#overallStatsChartDiv{
    min-height: 500px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<div class="chart" id="overallStatsChartDiv">
    <canvas id="overallStatsChart"></canvas>
</div>

Upvotes: 1

Related Questions