Skip to content

Commit 07109b6

Browse files
benmccannetimberg
authored andcommitted
[performance] replace helpers.each calls with for-loops (#6301)
* [performance] replace helpers.each calls with for-loops * Use Math.min/max instead of if statement * Rename variable
1 parent db6a6d5 commit 07109b6

File tree

5 files changed

+98
-99
lines changed

5 files changed

+98
-99
lines changed

src/core/core.helpers.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -553,25 +553,30 @@ module.exports = function() {
553553

554554
ctx.font = font;
555555
var longest = 0;
556-
helpers.each(arrayOfThings, function(thing) {
556+
var ilen = arrayOfThings.length;
557+
var i, j, jlen, thing, nestedThing;
558+
for (i = 0; i < ilen; i++) {
559+
thing = arrayOfThings[i];
560+
557561
// Undefined strings and arrays should not be measured
558562
if (thing !== undefined && thing !== null && helpers.isArray(thing) !== true) {
559563
longest = helpers.measureText(ctx, data, gc, longest, thing);
560564
} else if (helpers.isArray(thing)) {
561565
// if it is an array lets measure each element
562566
// to do maybe simplify this function a bit so we can do this more recursively?
563-
helpers.each(thing, function(nestedThing) {
567+
for (j = 0, jlen = thing.length; j < jlen; j++) {
568+
nestedThing = thing[j];
564569
// Undefined strings and arrays should not be measured
565570
if (nestedThing !== undefined && nestedThing !== null && !helpers.isArray(nestedThing)) {
566571
longest = helpers.measureText(ctx, data, gc, longest, nestedThing);
567572
}
568-
});
573+
}
569574
}
570-
});
575+
}
571576

572577
var gcLen = gc.length / 2;
573578
if (gcLen > arrayOfThings.length) {
574-
for (var i = 0; i < gcLen; i++) {
579+
for (i = 0; i < gcLen; i++) {
575580
delete data[gc[i]];
576581
}
577582
gc.splice(0, gcLen);
@@ -589,6 +594,10 @@ module.exports = function() {
589594
}
590595
return longest;
591596
};
597+
598+
/**
599+
* @deprecated
600+
*/
592601
helpers.numberOfLabelLines = function(arrayOfThings) {
593602
var numberOfLines = 1;
594603
helpers.each(arrayOfThings, function(thing) {

src/scales/scale.linear.js

Lines changed: 40 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -16,40 +16,36 @@ module.exports = LinearScaleBase.extend({
1616
var me = this;
1717
var opts = me.options;
1818
var chart = me.chart;
19-
var data = chart.data;
20-
var datasets = data.datasets;
19+
var datasets = chart.data.datasets;
2120
var isHorizontal = me.isHorizontal();
2221
var DEFAULT_MIN = 0;
2322
var DEFAULT_MAX = 1;
23+
var datasetIndex, meta, value, data, i, ilen;
2424

25-
function IDMatches(meta) {
26-
return isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id;
25+
function IDMatches(datasetMeta) {
26+
return isHorizontal ? datasetMeta.xAxisID === me.id : datasetMeta.yAxisID === me.id;
2727
}
2828

2929
// First Calculate the range
30-
me.min = null;
31-
me.max = null;
30+
me.min = Number.POSITIVE_INFINITY;
31+
me.max = Number.NEGATIVE_INFINITY;
3232

3333
var hasStacks = opts.stacked;
3434
if (hasStacks === undefined) {
35-
helpers.each(datasets, function(dataset, datasetIndex) {
36-
if (hasStacks) {
37-
return;
38-
}
39-
40-
var meta = chart.getDatasetMeta(datasetIndex);
41-
if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta) &&
42-
meta.stack !== undefined) {
35+
for (datasetIndex = 0; datasetIndex < datasets.length; datasetIndex++) {
36+
meta = chart.getDatasetMeta(datasetIndex);
37+
if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta) && meta.stack !== undefined) {
4338
hasStacks = true;
39+
break;
4440
}
45-
});
41+
}
4642
}
4743

4844
if (opts.stacked || hasStacks) {
4945
var valuesPerStack = {};
5046

51-
helpers.each(datasets, function(dataset, datasetIndex) {
52-
var meta = chart.getDatasetMeta(datasetIndex);
47+
for (datasetIndex = 0; datasetIndex < datasets.length; datasetIndex++) {
48+
meta = chart.getDatasetMeta(datasetIndex);
5349
var key = [
5450
meta.type,
5551
// we have a separate stack for stack=undefined datasets when the opts.stacked is undefined
@@ -69,64 +65,59 @@ module.exports = LinearScaleBase.extend({
6965
var negativeValues = valuesPerStack[key].negativeValues;
7066

7167
if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
72-
helpers.each(dataset.data, function(rawValue, index) {
73-
var value = me._parseValue(rawValue);
68+
data = datasets[datasetIndex].data;
69+
for (i = 0, ilen = data.length; i < ilen; i++) {
70+
value = me._parseValue(data[i]);
7471

75-
if (isNaN(value.min) || isNaN(value.max) || meta.data[index].hidden) {
76-
return;
72+
if (isNaN(value.min) || isNaN(value.max) || meta.data[i].hidden) {
73+
continue;
7774
}
7875

79-
positiveValues[index] = positiveValues[index] || 0;
80-
negativeValues[index] = negativeValues[index] || 0;
76+
positiveValues[i] = positiveValues[i] || 0;
77+
negativeValues[i] = negativeValues[i] || 0;
8178

8279
if (value.min === 0 && !opts.ticks.beginAtZero) {
8380
value.min = value.max;
8481
}
8582

8683
if (opts.relativePoints) {
87-
positiveValues[index] = 100;
84+
positiveValues[i] = 100;
8885
} else if (value.min < 0 || value.max < 0) {
89-
negativeValues[index] += value.min;
86+
negativeValues[i] += value.min;
9087
} else {
91-
positiveValues[index] += value.max;
88+
positiveValues[i] += value.max;
9289
}
93-
});
90+
}
9491
}
95-
});
92+
}
9693

9794
helpers.each(valuesPerStack, function(valuesForType) {
9895
var values = valuesForType.positiveValues.concat(valuesForType.negativeValues);
99-
var minVal = helpers.min(values);
100-
var maxVal = helpers.max(values);
101-
me.min = me.min === null ? minVal : Math.min(me.min, minVal);
102-
me.max = me.max === null ? maxVal : Math.max(me.max, maxVal);
96+
me.min = Math.min(me.min, helpers.min(values));
97+
me.max = Math.max(me.max, helpers.max(values));
10398
});
10499

105100
} else {
106-
helpers.each(datasets, function(dataset, datasetIndex) {
107-
var meta = chart.getDatasetMeta(datasetIndex);
101+
for (datasetIndex = 0; datasetIndex < datasets.length; datasetIndex++) {
102+
meta = chart.getDatasetMeta(datasetIndex);
108103
if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
109-
helpers.each(dataset.data, function(rawValue, index) {
110-
var value = me._parseValue(rawValue);
104+
data = datasets[datasetIndex].data;
105+
for (i = 0, ilen = data.length; i < ilen; i++) {
106+
value = me._parseValue(data[i]);
111107

112-
if (isNaN(value.min) || isNaN(value.max) || meta.data[index].hidden) {
113-
return;
108+
if (isNaN(value.min) || isNaN(value.max) || meta.data[i].hidden) {
109+
continue;
114110
}
115111

116-
if (me.min === null || value.min < me.min) {
117-
me.min = value.min;
118-
}
119-
120-
if (me.max === null || me.max < value.max) {
121-
me.max = value.max;
122-
}
123-
});
112+
me.min = Math.min(value.min, me.min);
113+
me.max = Math.max(value.max, me.max);
114+
}
124115
}
125-
});
116+
}
126117
}
127118

128-
me.min = isFinite(me.min) && !isNaN(me.min) ? me.min : DEFAULT_MIN;
129-
me.max = isFinite(me.max) && !isNaN(me.max) ? me.max : DEFAULT_MAX;
119+
me.min = helpers.isFinite(me.min) && !isNaN(me.min) ? me.min : DEFAULT_MIN;
120+
me.max = helpers.isFinite(me.max) && !isNaN(me.max) ? me.max : DEFAULT_MAX;
130121

131122
// Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero
132123
this.handleTickRangeOptions();

src/scales/scale.logarithmic.js

Lines changed: 39 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -72,38 +72,35 @@ module.exports = Scale.extend({
7272
var me = this;
7373
var opts = me.options;
7474
var chart = me.chart;
75-
var data = chart.data;
76-
var datasets = data.datasets;
75+
var datasets = chart.data.datasets;
7776
var isHorizontal = me.isHorizontal();
7877
function IDMatches(meta) {
7978
return isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id;
8079
}
80+
var datasetIndex, meta, value, data, i, ilen;
8181

8282
// Calculate Range
83-
me.min = null;
84-
me.max = null;
85-
me.minNotZero = null;
83+
me.min = Number.POSITIVE_INFINITY;
84+
me.max = Number.NEGATIVE_INFINITY;
85+
me.minNotZero = Number.POSITIVE_INFINITY;
8686

8787
var hasStacks = opts.stacked;
8888
if (hasStacks === undefined) {
89-
helpers.each(datasets, function(dataset, datasetIndex) {
90-
if (hasStacks) {
91-
return;
92-
}
93-
94-
var meta = chart.getDatasetMeta(datasetIndex);
89+
for (datasetIndex = 0; datasetIndex < datasets.length; datasetIndex++) {
90+
meta = chart.getDatasetMeta(datasetIndex);
9591
if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta) &&
9692
meta.stack !== undefined) {
9793
hasStacks = true;
94+
break;
9895
}
99-
});
96+
}
10097
}
10198

10299
if (opts.stacked || hasStacks) {
103100
var valuesPerStack = {};
104101

105-
helpers.each(datasets, function(dataset, datasetIndex) {
106-
var meta = chart.getDatasetMeta(datasetIndex);
102+
for (datasetIndex = 0; datasetIndex < datasets.length; datasetIndex++) {
103+
meta = chart.getDatasetMeta(datasetIndex);
107104
var key = [
108105
meta.type,
109106
// we have a separate stack for stack=undefined datasets when the opts.stacked is undefined
@@ -116,55 +113,56 @@ module.exports = Scale.extend({
116113
valuesPerStack[key] = [];
117114
}
118115

119-
helpers.each(dataset.data, function(rawValue, index) {
116+
data = datasets[datasetIndex].data;
117+
for (i = 0, ilen = data.length; i < ilen; i++) {
120118
var values = valuesPerStack[key];
121-
var value = me._parseValue(rawValue);
119+
value = me._parseValue(data[i]);
122120
// invalid, hidden and negative values are ignored
123-
if (isNaN(value.min) || isNaN(value.max) || meta.data[index].hidden || value.min < 0 || value.max < 0) {
124-
return;
121+
if (isNaN(value.min) || isNaN(value.max) || meta.data[i].hidden || value.min < 0 || value.max < 0) {
122+
continue;
125123
}
126-
values[index] = values[index] || 0;
127-
values[index] += value.max;
128-
});
124+
values[i] = values[i] || 0;
125+
values[i] += value.max;
126+
}
129127
}
130-
});
128+
}
131129

132130
helpers.each(valuesPerStack, function(valuesForType) {
133131
if (valuesForType.length > 0) {
134132
var minVal = helpers.min(valuesForType);
135133
var maxVal = helpers.max(valuesForType);
136-
me.min = me.min === null ? minVal : Math.min(me.min, minVal);
137-
me.max = me.max === null ? maxVal : Math.max(me.max, maxVal);
134+
me.min = Math.min(me.min, minVal);
135+
me.max = Math.max(me.max, maxVal);
138136
}
139137
});
140138

141139
} else {
142-
helpers.each(datasets, function(dataset, datasetIndex) {
143-
var meta = chart.getDatasetMeta(datasetIndex);
140+
for (datasetIndex = 0; datasetIndex < datasets.length; datasetIndex++) {
141+
meta = chart.getDatasetMeta(datasetIndex);
144142
if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) {
145-
helpers.each(dataset.data, function(rawValue, index) {
146-
var value = me._parseValue(rawValue);
143+
data = datasets[datasetIndex].data;
144+
for (i = 0, ilen = data.length; i < ilen; i++) {
145+
value = me._parseValue(data[i]);
147146
// invalid, hidden and negative values are ignored
148-
if (isNaN(value.min) || isNaN(value.max) || meta.data[index].hidden || value.min < 0 || value.max < 0) {
149-
return;
147+
if (isNaN(value.min) || isNaN(value.max) || meta.data[i].hidden || value.min < 0 || value.max < 0) {
148+
continue;
150149
}
151150

152-
if (me.min === null || value.min < me.min) {
153-
me.min = value.min;
154-
}
155-
156-
if (me.max === null || me.max < value.max) {
157-
me.max = value.max;
158-
}
151+
me.min = Math.min(value.min, me.min);
152+
me.max = Math.max(value.max, me.max);
159153

160-
if (value.min !== 0 && (me.minNotZero === null || value.min < me.minNotZero)) {
161-
me.minNotZero = value.min;
154+
if (value.min !== 0) {
155+
me.minNotZero = Math.min(value.min, me.minNotZero);
162156
}
163-
});
157+
}
164158
}
165-
});
159+
}
166160
}
167161

162+
me.min = helpers.isFinite(me.min) ? me.min : null;
163+
me.max = helpers.isFinite(me.max) ? me.max : null;
164+
me.minNotZero = helpers.isFinite(me.minNotZero) ? me.minNotZero : null;
165+
168166
// Common base implementation to handle ticks.min, ticks.max
169167
this.handleTickRangeOptions();
170168
},

test/specs/core.ticks.tests.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ describe('Test tick generators', function() {
4545
var xAxis = chart.scales['x-axis-0'];
4646
var yAxis = chart.scales['y-axis-0'];
4747

48-
expect(xAxis.ticks).toEqual(['-1', '-0.8', '-0.6', '-0.4', '-0.2', '0', '0.2', '0.4', '0.6', '0.8', '1']);
49-
expect(yAxis.ticks).toEqual(['1', '0.8', '0.6', '0.4', '0.2', '0', '-0.2', '-0.4', '-0.6', '-0.8', '-1']);
48+
expect(xAxis.ticks).toEqual(['0', '0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1']);
49+
expect(yAxis.ticks).toEqual(['1', '0.9', '0.8', '0.7', '0.6', '0.5', '0.4', '0.3', '0.2', '0.1', '0']);
5050
});
5151

5252
it('Should generate logarithmic spaced ticks with correct precision', function() {

test/specs/scale.linear.tests.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ describe('Linear Scale', function() {
453453
});
454454

455455
expect(chart.scales.yScale0).not.toEqual(undefined); // must construct
456-
expect(chart.scales.yScale0.min).toBe(-1);
456+
expect(chart.scales.yScale0.min).toBe(0);
457457
expect(chart.scales.yScale0.max).toBe(1);
458458
});
459459

@@ -829,10 +829,11 @@ describe('Linear Scale', function() {
829829
var chart = window.acquireChart({
830830
type: 'line',
831831
data: {
832+
labels: [-1, 1],
832833
datasets: [{
833834
xAxisID: 'xScale0',
834835
yAxisID: 'yScale0',
835-
data: []
836+
data: [-1, 1]
836837
}],
837838
},
838839
options: {

0 commit comments

Comments
 (0)