jmnavarro
jmnavarro

Reputation: 147

Performance issue using dc.js

I'm trying to make a simple dashboard using dc.js and bootstrap. The charts I'm showing are a simple series chart with three different series taken from a csv with approximately 9000 lines, a pie chart to select from those series and a bar chart to act as a date range selector.

It all works correctly but the performance is horrible. I assume it must be due to my lack of experience with crossfilter, as the example (http://nickqizhu.github.io/dc.js/) uses 6000 records and performs really fast. Any ideas? I'm sorry for the lack of concreteness but I'm a bit lost here.

My code is here:

d3.csv(sourceFile, function(error, data) {  
        data = data.splice(min,max);
        var parseDate = d3.time.format("%Y-%m-%d %H:%M:%S").parse;
        data.forEach(function(d) {
            d.Date = parseDate(d.date);
            d.Year=d.Date.getFullYear();
            d.Day = d3.time.day(d.Date);
        });
        var ndx2 = crossfilter(melt(data,["Date","Year","Day","date"],"Resource"));
        var meltedDim  = ndx2.dimension(function(d) {return d.Resource;});
        var dateDim = ndx2.dimension(function(d) {return d.Date;});
        var dateTypeDim = ndx2.dimension (function(d) {return [d.Date,d.Resource];});
        var valueGroup = dateTypeDim.group().reduceSum(function(d){return d.value});
        var dayDim = ndx2.dimension(function(d) {return d.Day;});
        var volumeByDayGroup = dayDim.group().reduceSum(function (d) {
            return d.value/50;
        });
        var yearDim  = ndx2.dimension(function(d) {return +d.Year;}); 
        var year_total = yearDim.group().reduceSum(function(d) {return d.value;});
        var resourceDim  = ndx2.dimension(function(d) {return d.Resource;});
        var value_resource = resourceDim.group().reduceSum(function(d) {return 1;}); 

        var minDate = dateDim.bottom(1)[0].Date;
        var maxDate = dateDim.top(1)[0].Date;

        var xAxisWidth = 1000;

        var dateRangePicker = dc.barChart("#rangeTable");
        dateRangePicker
            .width(xAxisWidth).height(80)
            .margins({top: 0, right: 10, bottom: 20, left: 65})
            .dimension(dayDim)
            .group(volumeByDayGroup)
            .x(d3.time.scale().domain([minDate,maxDate]))
            .gap(1)
            .round(d3.time.day.round)
            .elasticY(true)
            .xUnits(d3.time.days)
            .yAxis().ticks(4);

            var chart = dc.seriesChart(htmlID);
          chart
            .width(xAxisWidth).height(600)
           .dimension(dateDim)
           .group(valueGroup)
           .seriesAccessor(function(d) {return d.key[1]})
           .keyAccessor(function(d) {return d.key[0]})
           .valueAccessor(function (d) {return d.value})               
           .elasticY(false)
          .ordinalColors(["#56B2EA","#E064CD","#F8B700"])
           .x(d3.time.scale().domain([minDate,maxDate]))
           .y(d3.scale.linear().domain([0,100]))
           .elasticX(true)
           .margins({top: 10, right: 10, bottom: 00, left: 10})
           .brushOn(false)
           .transitionDuration(1000)
           .renderHorizontalGridLines(true)
           .renderVerticalGridLines(true)
           .rangeChart(dateRangePicker)
           .mouseZoomable(false)
           .legend(dc.legend().x(xAxisWidth-65).y(10).itemHeight(13).gap(5))
                   .margins({ top: 10, left: 50, right: 10, bottom: 50 }) 
           .yAxisLabel("Resource Percentage");




        var resourceRingChart = dc.pieChart("#chart-ring-resource");
        resourceRingChart
            .width(170).height(170)
            .ordinalColors(["#56B2EA","#E064CD","#F8B700"])
            .dimension(resourceDim)
            .group(value_resource)
            .legend(dc.legend().x(75).y(63).itemHeight(13).gap(5))
            .renderLabel(false)
            .renderTitle(false)
            .innerRadius(50); 



        //dc.renderAll();
        dateRangePicker.render();
        chart.render();
        resourceRingChart.render();



        function getvalues(d){
            var str=d.key.getDate() + "/" + (d.key.getMonth() + 1) + "/" + d.key.getFullYear()+"\n";
            var key_filter = dateDim.filter(d.key).top(Infinity);
            var total=0;
            key_filter.forEach(function(a) {
            str+=a.Resource+": "+a.value+"%\n";
            total+=a.value;
            });
            dateDim.filterAll();
            return str;
        } 

        $("#resetButton").on("click",function(){
           chart.filterAll();
           chart.y(d3.scale.linear().domain([0,100]));
           chart.render();
           dateRangePicker.filterAll();
           resourceRingChart.filterAll();
           dc.redrawAll();
           $("#rangeSlider").slider("destroy");
            $("#rangeSlider").slider({
             range: true,
             min: 0,
             max: 100,
             values: [0,100],
           });
        });

         $("#axisButton").on("click",function(){
            var min = $('#rangeSlider').slider("option", "values")[0];
            var max = $('#rangeSlider').slider("option", "values")[1];
            chart.y(d3.scale.linear().domain([min,max]));
            chart.render();
        });

        $("#rangeSlider").slider({
              range: true,
              min: 0,
              max: 100,
              values: [0,100],
            });
    })

Any help would be appreciated. Thanks in advance.

Upvotes: 1

Views: 1186

Answers (1)

jmnavarro
jmnavarro

Reputation: 147

When using dimensions, it's best to avoid strings,dates and complex objects. Turn everything you can into integers, as it sorts the contents of the data based on your variables.

Upvotes: 1

Related Questions