-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
setData mutating source array #4259
Comments
I'm seeing this as well |
Can you provide a demo? I set up a test case, but even when running 10 000 points the numbers are preserved in the original array. |
I created a trimmed-down version of the basic approach we're using [http://jsfiddle.net/LLExL/4807/]. However, as I mentioned, I can't trigger the exact use case (nor could I before). The only remaining significant difference between this example and the real code is there are 8 - 10 graphs (4 - 5 pairs just like the demo). Can you see any issues with the approach shown that may cause issues? |
There is one workaround that should be valid under any circumstance - if you copy (splice) the array before running setData, you are sure it isn't modified: series.setData(myData.splice(0)); |
Don't have a reliable repro either, but we also see this in 4.1.6. It seems to happen on certain charts with certain data, which doesn't make any sense. |
here is the demo. http://jsfiddle.net/xq29x6ja/3/ p.s. seems it is nothing about turboTreshold |
@pawel: Consider the fiddle above. Like we talked about earlier, creating a copy of of the source data is expensive, especially when dealing with a large amount of data. A leaner solution would be to identify the places where the source data is mutated, and do the copy there. Like in the case above, it is fixed by creating a copy in Find this code: // Record the options to options.data. If there is an object from before,
// use point options, otherwise use raw options. (#4701)
seriesOptions.data[i] = (isObject(seriesOptions.data[i]) && !isArray(seriesOptions.data[i])) ? point.options : options; Before it, add this code: // If this is the first time we're writing back to options.data, create
// a copy so that we don't mutate the source array. (#4259)
if (!seriesOptions.data.isCopy) {
seriesOptions.data = seriesOptions.data.slice();
seriesOptions.data.isCopy = true;
} What do you think? And do you have other cases of data source mutation where this fix doesn't work? |
The most popular are ones with
|
Yes, the first case is a different issue, but it raises another question. If we don't want to mutate the input options at all, it will require a wide range of changes in our source code. For example, the exported chart is based on the idea that the configuration options are mutated and kept in sync with the state of the chart. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions! |
Has this issue been addressed? If not, I feel the issue should not be closed. |
The current status of the issue is that creating a copy of data is too expensive (performance- and memory-wise). The issue is open, but undecided how it will be resolved - fixed through a code change or dismissed. As a workaround, you could provide a copy of the original data when using Highcharts. |
If I Object.freeze() the original data, Chart.update() seems to work still. Would you recommend this approach in addition to copying the data? |
If you make a deep copy @soetji then you don't need to use |
Thanks @pawelfus. Sorry that my question wasn't clear. In my example, my data was a plain array so I used I have a huge amount of data to display and need to preserve. So first, I want to avoid copying the data in order to preserve memory. Also I don't want Highcharts to change it. So I freeze the data. It seems that Highcharts still update properly with frozen data. Is this a recommended approach? |
Well, you just posted one of the reason why Highcharts does not copy the data. Memory and performance-wise most users don't care if the variable is unchanged (e.g. it's just a local variable from AJAX). The rest should pass on the copy of the dataset.
No, personally I don't recommend this approach because of the nested properties issue I explained above. From the maintenance of any application perspective it's the best to avoid caveats like the one with The only perfectly safe solution is to use deep-copy of the dataset in Highcharts API. |
i did an update from V 5.0.7 to 8.0.4 and using chart.Data as [ [Date,Data], [Date,Data] ....] is there any way of workaround? btw. if i use only Data array without Date this dont happen. |
Hi @Arut42
Yes, the one you posted: |
Hello, I faced the same issue. when i run these step
after setData, my dataSet will duplicate newPoint twice. And I found a workaround to prevent enter this part also refenence: https://api.highcharts.com/highcharts/plotOptions.series.cropThreshold |
We ran into the same issue with the We ended up spreading the series data into a new array when passed to our graph components, which works for our use case. |
How about adding a config option which would decide whether the input data is deep-copied by highcharts internally before mutating it? |
Hi!
That's a good idea. I'm tagging the ticket as a feature request. |
Seeing a strange behavior against Highcharts 4.1.5. When providing an Array of numbers (i.e, [1,2,3,4]), after some threshold the source array seems to be mutated into the following form:
[{y = 1}, {y=2}, {y=3}, {y=4}]
This seems to happen on larger sets of data (1300 - 1400 points + ), but we can't seem to get turboThreshold or cropThreshold to make a difference. Is there a setting we're missing, or is this a known bug?
Normally not an issue, but we're visualizing running time-series data windows and as a result are hanging on to the arrays we're calling setData() with. Once they are mutated, they are effectively "broke"...upstream sorting/binning code doesn't expect the inner objects, and stops working.
Thanks for your help!
The text was updated successfully, but these errors were encountered: