Skip to content

Commit

Permalink
[perf] cache resolved data element options (#6579)
Browse files Browse the repository at this point in the history
* [perf] cache resolved data element options
* Address review comments
* Move uninitialized variables, update comments
  • Loading branch information
kurkle authored and etimberg committed Oct 19, 2019
1 parent 959ea08 commit 6bc6630
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 5 deletions.
5 changes: 5 additions & 0 deletions src/controllers/controller.bubble.js
Expand Up @@ -154,6 +154,11 @@ module.exports = DatasetController.extend({
datasetIndex: me.index
};

// In case values were cached (and thus frozen), we need to clone the values
if (me._cachedDataOpts === values) {
values = helpers.extend({}, values);
}

// Custom radius resolution
values.radius = resolve([
custom.radius,
Expand Down
23 changes: 19 additions & 4 deletions src/core/core.datasetController.js
Expand Up @@ -290,6 +290,7 @@ helpers.extend(DatasetController.prototype, {
_update: function(reset) {
var me = this;
me._configure();
me._cachedDataOpts = null;
me.update(reset);
},

Expand Down Expand Up @@ -389,13 +390,16 @@ helpers.extend(DatasetController.prototype, {
*/
_resolveDataElementOptions: function(element, index) {
var me = this;
var custom = element && element.custom;
var cached = me._cachedDataOpts;
if (cached && !custom) {
return cached;
}
var chart = me.chart;
var datasetOpts = me._config;
var custom = element.custom || {};
var options = chart.options.elements[me.dataElementType.prototype._type] || {};
var elementOptions = me._dataElementOptions;
var values = {};
var keys, i, ilen, key;

// Scriptable options
var context = {
Expand All @@ -405,14 +409,21 @@ helpers.extend(DatasetController.prototype, {
datasetIndex: me.index
};

// `resolve` sets cacheable to `false` if any option is indexed or scripted
var info = {cacheable: !custom};

var keys, i, ilen, key;

custom = custom || {};

if (helpers.isArray(elementOptions)) {
for (i = 0, ilen = elementOptions.length; i < ilen; ++i) {
key = elementOptions[i];
values[key] = resolve([
custom[key],
datasetOpts[key],
options[key]
], context, index);
], context, index, info);
}
} else {
keys = Object.keys(elementOptions);
Expand All @@ -423,10 +434,14 @@ helpers.extend(DatasetController.prototype, {
datasetOpts[elementOptions[key]],
datasetOpts[key],
options[key]
], context, index);
], context, index, info);
}
}

if (info.cacheable) {
me._cachedDataOpts = Object.freeze(values);
}

return values;
},

Expand Down
10 changes: 9 additions & 1 deletion src/helpers/helpers.options.js
Expand Up @@ -115,9 +115,12 @@ module.exports = {
* is called with `context` as first argument and the result becomes the new input.
* @param {number} [index] - If defined and the current value is an array, the value
* at `index` become the new input.
* @param {object} [info] - object to return information about resolution in
* @param {boolean} [info.cacheable] - Will be set to `false` if option is not cacheable.
* @since 2.7.0
*/
resolve: function(inputs, context, index) {
resolve: function(inputs, context, index, info) {
var cacheable = true;
var i, ilen, value;

for (i = 0, ilen = inputs.length; i < ilen; ++i) {
Expand All @@ -127,11 +130,16 @@ module.exports = {
}
if (context !== undefined && typeof value === 'function') {
value = value(context);
cacheable = false;
}
if (index !== undefined && helpers.isArray(value)) {
value = value[index];
cacheable = false;
}
if (value !== undefined) {
if (info && !cacheable) {
info.cacheable = false;
}
return value;
}
}
Expand Down

0 comments on commit 6bc6630

Please sign in to comment.