From 82f6bc803b246f1d9a8ec54f5b1bba9c031596c0 Mon Sep 17 00:00:00 2001 From: Ludo Stellingwerff Date: Mon, 1 Feb 2016 11:58:33 +0100 Subject: [PATCH] Fixed initial load performance issue, triggered by failing comparison on Date objects. --- lib/timeline/component/LineGraph.js | 8 +++++--- lib/util.js | 15 ++++++++++----- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/lib/timeline/component/LineGraph.js b/lib/timeline/component/LineGraph.js index 1af1f1b8..961a293d 100644 --- a/lib/timeline/component/LineGraph.js +++ b/lib/timeline/component/LineGraph.js @@ -455,7 +455,6 @@ LineGraph.prototype._updateAllGroupData = function () { var extended = util.bridgeObject(item); extended.x = util.convert(item.x, 'Date'); extended.orginalY = item.y; //real Y - // typecast all items to numbers. Takes around 10ms for 500.000 items extended.y = Number(item.y); var index= groupsContent[groupId].length - groupCounts[groupId]--; @@ -792,8 +791,11 @@ LineGraph.prototype._getRelevantData = function (groupIds, groupsData, minDate, var itemsData = group.getItems(); // optimization for sorted data if (group.options.sort == true) { - var first = Math.max(0, util.binarySearchValue(itemsData, minDate, 'x', 'before')); - var last = Math.min(itemsData.length, util.binarySearchValue(itemsData, maxDate, 'x', 'after')+1); + var dateComparator = function (a, b) { + return a.getTime() == b.getTime() ? 0 : a < b ? -1 : 1 + }; + var first = Math.max(0, util.binarySearchValue(itemsData, minDate, 'x', 'before', dateComparator)); + var last = Math.min(itemsData.length, util.binarySearchValue(itemsData, maxDate, 'x', 'after', dateComparator) + 1); if (last <= 0) { last = itemsData.length; } diff --git a/lib/util.js b/lib/util.js index b653f069..ff325b1c 100644 --- a/lib/util.js +++ b/lib/util.js @@ -1352,16 +1352,21 @@ exports.binarySearchCustom = function (orderedItems, searchFunction, field, fiel * @param {{start: number, end: number}} target * @param {String} field * @param {String} sidePreference 'before' or 'after' + * @param {function} an optional comparator, returning -1,0,1 for <,==,>. * @returns {number} * @private */ -exports.binarySearchValue = function (orderedItems, target, field, sidePreference) { +exports.binarySearchValue = function (orderedItems, target, field, sidePreference, comparator) { var maxIterations = 10000; var iteration = 0; var low = 0; var high = orderedItems.length - 1; var prevValue, value, nextValue, middle; + var comparator = comparator != undefined ? comparator : function (a, b) { + return a == b ? 0 : a < b ? -1 : 1 + }; + while (low <= high && iteration < maxIterations) { // get a new guess middle = Math.floor(0.5 * (high + low)); @@ -1369,17 +1374,17 @@ exports.binarySearchValue = function (orderedItems, target, field, sidePreferenc value = orderedItems[middle][field]; nextValue = orderedItems[Math.min(orderedItems.length - 1, middle + 1)][field]; - if (value == target) { // we found the target + if (comparator(value, target) == 0) { // we found the target return middle; } - else if (prevValue < target && value > target) { // target is in between of the previous and the current + else if (comparator(prevValue, target) < 0 && comparator(value, target) > 0) { // target is in between of the previous and the current return sidePreference == 'before' ? Math.max(0, middle - 1) : middle; } - else if (value < target && nextValue > target) { // target is in between of the current and the next + else if (comparator(value, target) < 0 && comparator(nextValue, target) > 0) { // target is in between of the current and the next return sidePreference == 'before' ? middle : Math.min(orderedItems.length - 1, middle + 1); } else { // didnt find the target, we need to change our boundaries. - if (value < target) { // it is too small --> increase low + if (comparator(value, target) < 0) { // it is too small --> increase low low = middle + 1; } else { // it is too big --> decrease high