-
Notifications
You must be signed in to change notification settings - Fork 11.9k
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
Enable data decimation plugins by separating parsed data into two arrays #8251
Conversation
}; | ||
me.chart.notifyPlugins('afterDataParse', args); | ||
|
||
if (!isNullOrUndef(args.data)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd reverse the cases to avoid the !
@@ -591,7 +614,8 @@ export default class DatasetController { | |||
getMinMax(scale, canStack) { | |||
const me = this; | |||
const meta = me._cachedMeta; | |||
const _parsed = meta._parsed; | |||
// Use filtered parsed elements if the exist, otherwise the full elements |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't the correct array always available in the meta._parsed
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm storing the full array in meta._parsedRaw
and the filtered one in meta._parsed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if there is not filtered array, meta._parsed === meta._parsedRaw
?
|
||
if (numData > numMeta) { | ||
me._insertElements(numMeta, numData - numMeta); | ||
} else if (numData < numMeta) { | ||
me._removeElements(numData, numMeta - numData); | ||
} | ||
// Re-parse the old elements (new elements are parsed in _insertElements) | ||
me.parse(0, Math.min(numData, numMeta)); | ||
// me.parse(0, Math.min(numData, numMeta)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to do the parsing first and resync the element counts after that. So compare _data.length
to _parsedRaw.length
and if that differs parse. then compare _parsed.length
to numMeta
and add the elements. need to remove the parsing from the _insertElements.
@@ -998,7 +1023,7 @@ export default class DatasetController { | |||
data.splice(start, 0, ...elements); | |||
|
|||
if (me._parsing) { | |||
meta._parsed.splice(start, 0, ...new Array(count)); | |||
meta._parsedRaw.splice(start, 0, ...new Array(count)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can't do the parsing here at all, because start and count refer to elements, no to the raw data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'm realizing that this is causing a lot of tests to fail. A lot of code assumes these can be updated in sync at the same time.
I wonder if there is a simpler way to achieve this without touching the parsing, maybe even just a good guess at the size for estimating the number of points to keep
@@ -1014,7 +1039,7 @@ export default class DatasetController { | |||
const me = this; | |||
const meta = me._cachedMeta; | |||
if (me._parsing) { | |||
const removed = meta._parsed.splice(start, count); | |||
const removed = meta._parsedRaw.splice(start, count); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this might work, but against _parsed
@@ -60,7 +60,7 @@ export default class DoughnutController extends DatasetController { | |||
const meta = this._cachedMeta; | |||
let i, ilen; | |||
for (i = start, ilen = start + count; i < ilen; ++i) { | |||
meta._parsed[i] = +data[i]; | |||
meta._parsedRaw[i] = meta._parsed[i] = +data[i]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should do only one array and set the other to same instance after loop. we should make sure _parsedRaw
is sufficient sized before parsing, so should set to that.
// to ensure that decimation plugins can take advantage of the | ||
// scale dimensions | ||
const controller = me.getDatasetMeta(i).controller; | ||
controller._notifyAfterParse(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we call this _notifyAfterLayout
?
Edit: I see now why this was called _notifyAfterParse
. I think it could be called _notifyAfterLayout
if we were not setting data
attribute in the args
per the suggestion in https://github.com/chartjs/Chart.js/pull/8251/files#r550253989
const {_cachedMeta: meta} = me; | ||
const {iScale} = meta; | ||
|
||
// We expect afterDataParse hooks to set the modified data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it'd be cleaner to always set meta._parsed = meta._parsedRaw
and then have the plugin override meta._parsed
. We could expose a setParsed
method if that's preferable to setting the value of private _parsed
variable. We might have to pass chart
as an arg so that we can get the meta
Closing this since #8255 went a lot better |
Enables plugins via a new hook
afterDataParse
.To Do
Testing
I tested this on the uPlot benchmark over 100 runs. It performs noticeably better than the mainline code
master
PR + decimation plugin
The plugin i used is below.