Line charts performance - javascript

I'm trying to get maximum performance for my line charts with LightningChart JS. From the performance example, I learned the max point count I can run with the performance tester is 10 series x 1 million point each. I configure it like this .
I can run it with 30-40 refreshes / second.
Two questions:
Is there an easy way to test it with higher point counts? Any on-line demo/tester for that?
Is there general guidelines for optimizing the performance settings with this JavaScript Lightning Chart?

Test with more points
There isn't currently any online tester that has higher point counts than that. But the source code for the tester you have used is available in GitHub: https://github.com/Arction/lcjs-performance-tester
The repository has good instructions how to run it locally.
To add a test with more points you can edit the content/src/tests/default.js file and add a new test that has the point count you would like to test with. Let's say you would like to have 10 series with 2 million points each. You could add
{
key: '2M',
label: '2 M points',
code: (thickness) => ScrollingProgressiveLine(2 * 1000 * 1000, seriesCount, thickness.thickness, `${seriesCount} Scrolling Line Series 2 000 000 points each ${thickness.label}`),
defaultSelected: false
},
after line 718, between the 1M and 10M points tests. The last test on that list is excluded from being an actual runnable test.
There is also a showcase example that can be used to see how many points the chart can display while maintaining 60 fps. https://arction.github.io/lcjs-showcase-streamingData/
Optimizing performance
Set DataPattern based on the data you are using when creating a new series.
For line series it's set with dataPattern property in line series options. chart.addLineSeries({dataPattern: DataPatterns.horizontalProgressive})
Disable animations.
I have already answered how to disable animations in How to disable animations for charts in LightningChart JS?.
Disable mouse interactions.
To disable mouse interactions you can call .setMouseInteractions(false) on all axes, series and charts.
Disable Auto Cursor.
To do this call setAutoCursorMode with AutoCursorModes.disabled as a parameter.

Related

How to modify the 'nodes' behaviour in Zingchart

I plot some series of data with Zingchart. The data is one entry per second, per set. The result is the following graph:
.
I am happy with this result. I get an overview of the plot that is very fast using "exact":false as plot attribute. Afterwards, I want to be able to 'zoom in' to see the detail:
And now I have too much detail. The attributes I have for plot are:
"maxNodes":2000,
"maxTrackers":2000,
I have been trying to play with those numbers but at the end, if I reduce the number I just have to zoom-in more. As I understand I get one node/tracker/information popup per data entry in the current status of the visualization only if there are less nodes than the limit defined.
Would it be possible to indicate Zingchart to place the nodes not in every data point, but with some kind of interval or intention?.
For example, in the second graph I would like to have nodes at the beginning / end and on the jump that the line makes. Or local maximums / minimums.
There are a few options.
1) You could change the "max-nodes" to a lower number. "max-nodes" just determines how many nodes are drawn while "max-trackers" determines how many you can interact with.
2) You could also add the following to your plot object...
marker: {
rules: [
{
rule: '%i%5 > 0',
visible: false
}
]
}
What that does it it checks the index (%i) of each marker. If the index of the marker modulo 5 is greater than 0, we don't display the marker (node). That means that all nodes except those evenly divisible by 5 will be hidden.
I'm on the ZingChart team. Let me know if this helps. Holla if you've got more questions.

Best performance for updating many Highcharts instances on demand

I currently have a page with some Highcharts graphics, around 22, and they are subject to filters selectable by the user. Each filter interaction removes the current series and adds new ones.
I started with two approaches, the first consisted in having a loop that went through all saved instance objects, removing each serie,
while currentChart.series.length > 0
currentChart.series[currentChart.series.length - 1].remove()
and then, after another loop that goes through arrays to search for the filter data and
currentChart.addSeries
name: operatorName
data: data
type: options.chartType
but this implementation turned out to be quite heavy.
I then implemented a timeout to let the plugin breathe a little and don't stack as much, by setting a 1ms timeout between each loop I got better performance and could see the animations but It makes it a bit sluggish. Setting a higher timeout makes the page hard to navigate and filter changes would stack, as the entire graphics update would take much time.
In my experience, when I have a large number of charts or datapoints, I generally turn off animation. Animation adds a lot over processing overhead, and without it highcharts generally handles a lot of data very well.
I guess you could try removing the series and adding the new one for each chart at a time, rather than removing all and then adding all. I doublt this will make much different to your page responsiveness though.
chart: {
animation: false
},
plotOptions: {
series: {
animation: false
}
},
while currentChart.series.length > 0
currentChart.series[0].destroy()
ex: http://jsfiddle.net/5B9c7/1/

Strange tooltip behavior with long series in highcharts

I'm using Highcharts for a project in which I have to display two series with about a thousand points each. The x-axis represents a date, and the y-axis a quantity. In addition, each point has an associated list of namesMy data is day-by-day without gaps, with a structure such as
var mydata = [ ...
{x: theDate, y: theValue, names: theNames},
... ]
where theNames is an array of strings. I can access these in the tooltip formatter through this.points.point.names, given that the range displayed on the chart is small enough. If I change the x-axes so that the start date and end date are more than roughly a year apart, then the tooltip is not rendered at all.
One of the possible avenues that I have tried but failed with so far is setting the turboThreshold limit to the length of the longest series plus 1. Setting this lets me at least display a graph when mydata.length > 1000 (the default value). However, this only displays the tooltip if the x-axis range is less than 261. Otherwise, the tooltip disappears entirely, as does the point.data object where I'm getting the name from.
I'm also not great at JavaScript, but I was wondering if there were a way to separate the names of the points from the array containing them (in my examples, myData1 and myData2) and somehow access those names from the tooltip function without going through the current point.
Here is the link to the jsFiddle demonstrating this issue.
All help is appreciated!
The problem is in dataGrouping, when disabled works fine: http://jsfiddle.net/34tfg/1/
DataGrouping is method in Highcharts to approximate points and display them when width of the chart is not enough, e.g. how to display 10 000points in a chart of width 1 000px -> 10 points in a one pixel..? And when dataGrouping is used, new points are created, so all your custom options like 'names' etc. are lost (at least not accessible).
Code:
plotOptions: {
line: {
dataGrouping: {
enabled: false
},
turboThreshold: 10000
}
},

d3: multiple lines same graph with varying y domains?

I have data which is all time series, so the x axis of my d3 graph is always time. I need to support having multiple lines on one graph, but the different lines can have vastly different domains for the y axis data. For example line 1 can be
1 2 3 4 5 for times 1-5
5000 10000 15000 20000 25000 for times 1-5
What is a good way to try to handle this in d3?
You could have two separate Y axes. One on the left hand side of the graph and one on the right.
This post describes setting up a two line graph. http://www.d3noob.org/2013/01/adding-more-than-one-line-to-graph-in.html
And this post describes setting two different y axes for the lines with a similar scale problem to the one you describe. http://www.d3noob.org/2013/01/using-multiple-axes-for-d3js-graph.html
The end result is something like this.
I would recommend a log scale if you don't have zeros for the y values. In any case, simply create a single y scale that ranges from the minimum to the maximum of all lines and use that for everything.
Have you considered stacking two plots on identical x-axis scales? Or for a rapid comparison, I sometimes re-scale one data series to bring it into the domain of the other, then note it in the legend. "series 1 (x10 scaling)"

Charting thousands of points with dojo

I need to plot thousands of points, perhaps close to 50,000 with the dojo charting library. It works, but it's definitely very slow and lags the browser. Is there any way I can get better performance?
EDIT:
I solved by applying a render filter to the data. Essentially, I have a new item parameter called "render" which is set to false by my json source if the point is expected to overlap others. My DataSeries then queries for all points where render:true. This way all of the data is there still for non-visual sources that want all of the points, while my charts now run smoothly.
Psuedocode:
def is_overlapped(x, y, x_round, y_round)
rounded_x = round(x, x_round)
rounded_y = round(y, y_round)
hash = hash_xy(rounded_x, rounded_y)
if(#overlap_filter[hash].nil?)
#overlap_filter[hash] = true
return false
end
return true
end
x_round and y_round can be determined by the x and y ranges, say for example range / 100
I know this isn't probably exactly the answer you're looking for, but have you considered simply reducing the number of points you are plotting? I don't know the specific function of the graph(s), but I'd imagine most graphs with that many points are unnecessary; and no observer is going to be able to take that level of detail in.
Your solution could lie with graphing techniques rather than JavaScript. E.g. you could most likely vastly reduce the number of points and use a line graph instead of a scatter plot while still communicating similar levels of information to your intended target.

Categories