The speed of nvd3 when used in conjunction with angular-nvd3 is abysmally slow

I can't seem to figure out what's causing an issue in my application. Every second, I need to update 5000 points (5 array elements with 1000 x,y points) on the client side using NVD3 in an AngularJS app. The problem is that it's slowing down the whole application, and Chrome's developer tools show a delay of 5-6 seconds due to d3_timer_step.

I initially thought it was a data updating problem, but it seems like the bottleneck lies within the d3 component. Here's a snippet of the code:

<nvd3 options="optionsRingdown" data="ringdownAvg" config="{refreshDataOnly:true}"></nvd3>

The controller defines the options as follows:

$scope.options = {
    chart: {
      type: 'lineChart',
      height: 300,
      margin: {
        top: 20,
        right: 40,
        bottom: 60,
        left: 75
      },
      x: function(d) {
        return d.x;
      },
      y: function(d) {
        return d.y;
      },
      useInteractiveGuideline: false,
      yAxis: {
        tickFormat: function(d) {
          return d3.format('0.01f')(d);
        },
        axisLabel: 'Testing'
      },
      xAxis: {
        tickFormat: function(d) {
          return d3.time.format('%X')(new Date(d));
        },
        rotateLabels: -45
      },
      transitionDuration: 0,
      showXAxis: true,
      showYAxis: true
    }
  };

The data template looks like this:

var ringdownT = [{
   values: [],
   key: 'Cell 0'
 }, {
   values: [],
   key: 'Cell 1'
 }, {
   values: [],
   key: 'Cell 2'
 }, {
   values: [],
   key: 'Cell 3'
 }, {
   values: [],
   key: 'Cell 4'
 }];

Data is updated through a service broadcast using:

function updateCRD(d){
   var dataOut = {
     "tauData": [],
     "rdFit": ringdownT,
     "rdAvg":ringdownT
   }
   for (k = 0; k < d.cell.length; k++) {
     dataOut.rdAvg[k].values = d.cell[k].avg_rd;
     dataOut.rdFit[k].values = d.cell[k].fit_rd;
   }

   return dataOut;
}

The function is triggered in a broadcast at one-second intervals:

$scope.$on('dataAvailable', function() {

    $scope.data = Data.crd;

    var data = updateCRD(Data.crd);

    $scope.tauData = data.tauData;
    $scope.ringdownAvg = data.rdAvg;
    $scope.ringdownFit = data.rdFit;
});

If anyone sees any obvious issues or has suggestions for improvement, please let me know. Any help would be greatly appreciated.

Thanks, Matt

Answer №1

To enhance the performance of your directive, consider adding the deepWatchData: false flag to the configuration. This will prevent the directive from constantly watching for data updates. Instead, you can manually update the chart using the api:

<nvd3 options="optionsRingdown" data="ringdownAvg" api="apiRingdown" config="{refreshDataOnly:true, deepWatchData: false}"></nvd3>

The directive normally uses the $watch method to monitor changes in options and complex data objects. Setting deepWatchData to false disables this behavior.

In Angular versions 1.0.2 and 1.0.3, deepWatchData is set to false by default due to memory and performance concerns when watching complex objects.


To update the chart, utilize the apiRingdown.update() method in your controller:

$scope.$on('dataAvailable', function() {

    $scope.data = Data.crd;

    var data = updateCRD(Data.crd);

    $scope.tauData = data.tauData;
    $scope.ringdownAvg = data.rdAvg;
    $scope.ringdownFit = data.rdFit;

    //this line updates the chart
    $scope.apiRingdown.update();
});

UPDATED

In newer versions (1.0.4+), deepWatchData now controls whether data should be watched at all, rather than just for object equality as before. The default value for deepWatchData is now true. Additionally, a new flag deepWatchDataDepth: 2 allows for specifying the depth of change detection, offering more control over performance optimization:

0 - By Reference
1 - By Collection Items
2 - By Value (default)

The refreshDataOnly flag is also set to true by default.

An updated tag element with these modifications may look like:

<nvd3 options="optionsRingdown" data="ringdownAvg" api="apiRingdown" config="{deepWatchDataDepth: 0}"></nvd3>

Check out this demo for an example.

Answer №2

Are you utilizing SVG? It appears that nvd3.lineChart is based on SVG, so most likely yes. If you are, @mbostock has a helpful resource for you: http://bl.ocks.org/mbostock/1276463. Consider using canvas instead of SVG for improved speed.

Many useful suggestions can be found at .

If you find yourself redrawing all 5000 points each second, perhaps consider utilizing webGL instead of nvd3. Alternatively, canvas might provide the necessary speed boost. Assess the performance and make an informed decision based on your requirements.

Take notice of the time spent in d3_timer_step. While this function may not inherently be slow, it could be called frequently leading to performance issues. Also, keep an eye on d3_timer_frame which is invoked by d3_timer_step - this might be where the rendering bottleneck lies. Experiment with switching to canvas for potential improvements.

Possible enhancements for nvd3 performance:

  1. If you haven't already, disable useInteractiveGuideline as it could contribute to inefficiencies.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The reason for the additional backward slashes in the JSON Response from the browser and the incorrect JSON array length is unclear

Here is an example of how I am sending a callback request to the server for a JSON Value: $(document).on('click', '.currentOrderRow', function(event ) { var orderid = $(this).attr("id_data"); $.ajax({ type: 'GET', ...

Expanding the width of Material UI Javascript Dialog Box

Currently, I am utilizing the dialog feature from Material UI in my React JS project and I am looking to expand its width. After some research, I discovered that there is a property called maxWidth which allows you to adjust the width of the dialog. Howe ...

The complete rendering of angular-google-maps is only achieved after resizing the browser

<ui-gmap-google-map center="{latitude: 43.100187, longitude: -77.6329959}" zoom='8'> </ui-gmap-google-map> https://i.sstatic.net/9F2eb.jpg All necessary files were loaded via bower and the dependency was added t ...

How can you append an object with a defined key to an array in Vue?

Currently developing a vue-application that includes a component for managing driving licenses. Here is an overview of my data setup: data() { return { custom_licenses: [], basic_licenses: [] } } Within my methods, I have the following l ...

NodeJs and Mysql query execution experiencing significant delays

NodeJs + Mysql query delays and execution timing issue https://github.com/mysqljs/mysql Hello everyone, I'm facing a problem with mysql js. Whenever I use .query(), the callback is taking too long to execute and returning empty results. However, if I ...

Please ensure that all fields in the form are filled out before clicking the enable button

Is it possible to enable the button only when all fields are filled out in a form? It's easy if there's just one field, but I have multiple fields with a select field as well. I'm not sure how to do this. Here's the form I've creat ...

Transform the click event of a calendar button from Jquery into an Angular directive

Looking to transform my jQuery button click code into an Angular directive. Here's the snippet of code I currently have: $('.fc-month-button').click(); ...

Utilizing Express to load a uniform static website across all website paths

On my express server, I attempted to make all paths load the same static website using this code: const express = require('express'); const app = express(); app.use('*', express.static('build')); app.listen(3000); But every ...

"Exploring Angular UI-Router by conducting tests with the help of Mocha,

Experimenting with testing the following code in AngularJS using Mocha, Chai, and Sinon. $scope.send = function() { $state.transitionTo('module.sendhome'); }; Here is a test case for validation: it('send' , function () { scop ...

Is there an issue with using $_POST in an ajax form submission?

Whenever I attempt to verify if a user-inputted name already exists through an ajax form submission, all I receive is an error stating "Undefined index: username" in the sessions.php file. What could be causing this issue? <form action="" method="POST" ...

Are there any uncomplicated JavaScript tools for creating spreadsheets?

I am in the process of developing a basic web-based expense calculator using asp.net web forms. Each cell will contain a text box, and the objective is to save each value (excluding the totals) to a database. I plan to have an expense table and an expense_ ...

How can I trigger a CSS animation to replay each time a button is clicked, without relying on a timeout function?

I am having trouble getting a button to trigger an animation. Currently, the animation only plays once when the page is refreshed and doesn't repeat on subsequent clicks of the button. function initiateAnimation(el){ document.getElementById("anima ...

What is the best way to apply a color overlay to an image using CSS?

In my current project, I am utilizing React along with HTML, CSS, and Material UI. One of the tasks I am working on is toggling a color overlay on an image when it is clicked. Here is the snippet of JavaScript code I have implemented: const About = ({imgS ...

Interactive image rotator featuring navigation buttons for next and previous slides

I recently followed a tutorial from W3Schools Now, I am looking to enhance it by adding previous / next buttons for the indicators, rather than for the slider itself Here is what I aim to accomplish: https://i.sstatic.net/qH1PQ.png Below is the code sn ...

I am looking for a way to generate unique dynamic IDs for each input textbox created within a PHP while loop. Can

How can I retrieve the ID of a selected text box generated within a while loop in order to update a field similar to phpMyAdmin? <?php while($row=mysql_fetch_assoc($result)) { ?> <tr> <td><input type ...

Exploring the process of connecting search values in MongoDB using Mongoose

In the /search/:query route, I have the code snippet shown below: var param = { query: req.query['query'] } MyModel.find({ "$or": [ { 'name': req.param.query }, { 'age': req.param.query } ...

Having trouble assigning select values from my Angular JS controller

This specific scenario My attempt to change the selected value in the dropdown from the controller isn't working as expected, despite following guidance from various questions on this platform. The only unique aspect in my case is that I have a defau ...

Retrieving data from the chosen selection in AngularJS

My current task involves extracting the URL from the selected option and assigning it to the ng-model of the select element. Here is the HTML code snippet: <select ng-model="ddValue1.value"> <option ng-repeat="d in ddOptions1" value="{{d.val ...

React Grid by DevExtreme

Does anyone have a solution for adjusting the fontSize of the TableHeaderRow in a DevExtreme React Grid? Here is some code from a specific website () that I've been exploring: import * as React from 'react'; // Other imports... const Ad ...

Angular Singleton Service for Asynchronous UI-Router Operations

I've been using UI-Router for my Angular application. The data I fetch through an asynchronous $http call helps in creating a connection object, which I want to make available as a singleton. My aim is to prevent potential timing issues that may arise ...