Skip to content

Commit

Permalink
Review comments, more time scale optimization
Browse files Browse the repository at this point in the history
  • Loading branch information
kurkle committed Nov 7, 2019
1 parent 16bd850 commit e7121ed
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 65 deletions.
20 changes: 7 additions & 13 deletions src/core/core.datasetController.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
var helpers = require('../helpers/index');

var resolve = helpers.options.resolve;
var isNullOrUndef = helpers.isNullOrUndef;

var arrayEvents = ['push', 'pop', 'shift', 'splice', 'unshift'];

Expand Down Expand Up @@ -140,17 +139,12 @@ function getFirstScaleId(chart, axis) {
}

function getUserBounds(scale) {
var min = scale._userMin;
var max = scale._userMax;
if (isNullOrUndef(min) || isNaN(min)) {
min = Number.NEGATIVE_INFINITY;
}
if (isNullOrUndef(max) || isNaN(max)) {
max = Number.POSITIVE_INFINITY;
}
return {min, max};
var {min, max, minDefined, maxDefined} = scale._getUserBounds();
return {
min: minDefined ? min : Number.NEGATIVE_INFINITY,
max: maxDefined ? max : Number.POSITIVE_INFINITY
};
}

// Base class for all dataset controllers (line, bar, etc)
var DatasetController = function(chart, datasetIndex) {
this.initialize(chart, datasetIndex);
Expand Down Expand Up @@ -588,7 +582,7 @@ helpers.extend(DatasetController.prototype, {
var stacked = canStack && meta._stacked;
var indices = getSortedDatasetIndices(chart, true);
var otherScale = this._getOtherScale(scale);
var otherScaleBounds = getUserBounds(otherScale);
var {otherMin, otherMax} = getUserBounds(otherScale);
var i, item, value, parsed, stack, min, minPositive, otherValue;

min = minPositive = Number.POSITIVE_INFINITY;
Expand All @@ -599,7 +593,7 @@ helpers.extend(DatasetController.prototype, {
value = parsed[scale.id];
otherValue = parsed[otherScale.id];
if (item.hidden || isNaN(value) ||
otherScaleBounds.min > otherValue || otherScaleBounds.max < otherValue) {
otherMin > otherValue || otherMax < otherValue) {
continue;
}
if (stacked) {
Expand Down
44 changes: 30 additions & 14 deletions src/core/core.scale.js
Original file line number Diff line number Diff line change
Expand Up @@ -354,33 +354,49 @@ var Scale = Element.extend({
return null;
},

/**
* @private
* @since 3.0
*/
_getUserBounds: function() {
var min = this._userMin;
var max = this._userMax;
if (isNullOrUndef(min) || isNaN(min)) {
min = Number.POSITIVE_INFINITY;
}
if (isNullOrUndef(max) || isNaN(max)) {
max = Number.NEGATIVE_INFINITY;
}
return {min, max, minDefined: isFinite(min), maxDefined: isFinite(max)};
},

/**
* @private
* @since 3.0
*/
_getMinMax: function(canStack) {
var me = this;
var min = Number.POSITIVE_INFINITY;
var max = Number.NEGATIVE_INFINITY;
var {min, max, minDefined, maxDefined} = me._getUserBounds();
var minPositive = Number.POSITIVE_INFINITY;
var i, ilen, metas, minmax;

if (isFinite(me._userMin) && isFinite(me._userMax)) {
return {
min: me._userMin,
max: me._userMax
};
if (minDefined && maxDefined) {
return {min, max};
}

metas = me._getMatchingVisibleMetas();
for (i = 0, ilen = metas.length; i < ilen; ++i) {
minmax = metas[i].controller._getMinMax(me, canStack);
min = Math.min(min, minmax.min);
max = Math.max(max, minmax.max);
if (!minDefined) {
min = Math.min(min, minmax.min);
}
if (!maxDefined) {
max = Math.max(max, minmax.max);
}
minPositive = Math.min(minPositive, minmax.minPositive);
}

return {
min: min,
max: max,
minPositive: minPositive
};
return {min, max, minPositive};
},

_invalidateCaches: helpers.noop,
Expand Down
116 changes: 78 additions & 38 deletions src/scales/scale.time.js
Original file line number Diff line number Diff line change
Expand Up @@ -364,49 +364,63 @@ function ticksFromTimestamps(scale, values, majorUnit) {
return (ilen === 0 || !majorUnit) ? ticks : setMajorTicks(scale, ticks, map, majorUnit);
}


function getDataTimestamps(scale) {
var timestamps = scale._cache.data || [];
var i, ilen, metas;

if (!timestamps.length) {
metas = scale._getMatchingVisibleMetas();
for (i = 0, ilen = metas.length; i < ilen; ++i) {
timestamps = timestamps.concat(metas[i].controller._getAllParsedValues(scale));
}
timestamps = scale._cache.data = arrayUnique(timestamps).sort(sorter);
if (timestamps.length) {
return timestamps;
}

metas = scale._getMatchingVisibleMetas();
for (i = 0, ilen = metas.length; i < ilen; ++i) {
timestamps = timestamps.concat(metas[i].controller._getAllParsedValues(scale));
}

if (ilen > 1 && scale.options.distribution === 'series') {
timestamps = arrayUnique(timestamps).sort(sorter);
}

scale._cache.data = timestamps;

return timestamps;
}

function getLabelTimestamps(scale) {
var timestamps = scale._cache.labels || [];
var i, ilen, labels;

if (!timestamps.length) {
labels = scale._getLabels();
for (i = 0, ilen = labels.length; i < ilen; ++i) {
timestamps.push(parse(scale, labels[i]));
}
timestamps = scale._cache.labels = arrayUnique(timestamps).sort(sorter);
if (timestamps.length) {
return timestamps;
}

labels = scale._getLabels();
for (i = 0, ilen = labels.length; i < ilen; ++i) {
timestamps.push(parse(scale, labels[i]));
}

scale._cache.labels = timestamps;

return timestamps;
}

function getAllTimestamps(scale) {
var timestamps = scale._cache.all || [];
var label, data;

if (!timestamps.length) {
data = getDataTimestamps(scale);
label = getLabelTimestamps(scale);
if (data.length && label.length) {
timestamps = arrayUnique(data.concat(label)).sort(sorter);
} else {
timestamps = data.length ? data : label;
}
timestamps = scale._cache.all = timestamps;
if (timestamps.length) {
return timestamps;
}

data = getDataTimestamps(scale);
label = getLabelTimestamps(scale);
if (data.length && label.length) {
timestamps = arrayUnique(data.concat(label)).sort(sorter);
} else {
timestamps = data.length ? data : label;
}
timestamps = scale._cache.all = timestamps;

return timestamps;
}

Expand All @@ -430,6 +444,24 @@ function getTimestampsForTicks(scale) {
return timestamps;
}

function getTimestampsForTable(scale) {
return scale.options.distribution === 'series'
? getAllTimestamps(scale)
: [scale.min, scale.max];
}

function getLabelBounds(scale) {
var min = Number.POSITIVE_INFINITY;
var max = Number.NEGATIVE_INFINITY;
var arr = getLabelTimestamps(scale);

if (arr.length) {
min = arr[0];
max = arr[arr.length - 1];
}
return {min, max};
}

/**
* Return subset of `timestamps` between `min` and `max`.
* Timestamps are assumend to be in sorted order.
Expand Down Expand Up @@ -546,27 +578,35 @@ module.exports = Scale.extend({

determineDataLimits: function() {
var me = this;
var options = me.options;
var adapter = me._adapter;
var unit = me.options.time.unit || 'day';
var min = Number.POSITIVE_INFINITY;
var max = Number.NEGATIVE_INFINITY;
var minmax = me._getMinMax(false);
var labels = getLabelTimestamps(me);

min = Math.min(min, minmax.min);
max = Math.max(max, minmax.max);

if (labels.length) {
min = Math.min(min, labels[0]);
max = Math.max(max, labels[labels.length - 1]);
var unit = options.time.unit || 'day';
var {min, max, minDefined, maxDefined} = me._getUserBounds();

function _apply(bounds) {
if (!minDefined && !isNaN(bounds.min)) {
min = Math.min(min, bounds.min);
}
if (!maxDefined && !isNaN(bounds.max)) {
max = Math.max(max, bounds.max);
}
}

// If we have user provided `min` and `max` labels / data bounds can be ignored
if (!minDefined || !maxDefined) {
// Labels are always considered, when user did not force bounds
_apply(getLabelBounds(me));

// If `bounds` is `'ticks'` and `ticks.source` is `'labels'`,
// data bounds are ignored (and don't need to be determined)
if (options.bounds !== 'ticks' || options.ticks.source !== 'labels') {
_apply(me._getMinMax(false));
}
}

min = helpers.isFinite(min) && !isNaN(min) ? min : +adapter.startOf(Date.now(), unit);
max = helpers.isFinite(max) && !isNaN(max) ? max : +adapter.endOf(Date.now(), unit) + 1;

min = me._userMin || min;
max = me._userMax || max;

// Make sure that max is strictly higher than min (required by the lookup table)
me.min = Math.min(min, max);
me.max = Math.max(min + 1, max);
Expand Down Expand Up @@ -601,7 +641,7 @@ module.exports = Scale.extend({
: determineUnitForFormatting(me, ticks.length, timeOpts.minUnit, me.min, me.max));
me._majorUnit = !tickOpts.major.enabled || me._unit === 'year' ? undefined
: determineMajorUnit(me._unit);
me._table = buildLookupTable(getAllTimestamps(me), min, max, distribution);
me._table = buildLookupTable(getTimestampsForTable(me), min, max, distribution);
me._offsets = computeOffsets(me._table, ticks, min, max, options);

if (tickOpts.reverse) {
Expand Down

0 comments on commit e7121ed

Please sign in to comment.