-
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
Use binary search for interpolations #6958
Conversation
Master is not that bad now, because #6953 was already merged :) |
src/core/core.interaction.js
Outdated
if (!element.skip) { | ||
handler(element, metaset.index, index); | ||
const {index, data} = metasets[i]; | ||
const {lo, hi, loIndex, hiIndex} = lookup(data, axis, position[axis]); |
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 don't understand why this is returning two items. Shouldn't the data be located just at one index? It seems like handler
could be called extra times and after the time scale is split we may not need the "lo" and "hi" concept but then still be using it here
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.
With caching of dimensions: var start = Date.now();
var rect = chart.canvas.getBoundingClientRect();
for (var i = 0; i < 100000; i++) {
var ix = Math.round(Math.random() * 55549);
var point = chart._metasets[0].data[ix];
var event = {
type: 'mousemove',
target: chart.canvas,
clientX: rect.left + point.x,
clientY: rect.top + point.y,
cancelable: true,
bubbles: true,
view: window
};
chart.getElementsAtEventForMode(event, 'nearest', {intersect: false, axis: 'x'});
}
console.log(Date.now() - start); master: ~750ms |
src/core/core.interaction.js
Outdated
@@ -112,7 +109,7 @@ function getIntersectItems(chart, position, axis) { | |||
} | |||
}; | |||
|
|||
const optimized = evaluateItemsAtIndex(chart, axis, position, evaluationFunc); | |||
const optimized = binarySearchItems(chart, axis, position, evaluationFunc); |
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 just realized this might not technically be correct (eventhough I introduced it). Imagine you have very large points that are all overlapping with the given position. Just returning the items at the nearest index might not be enough because there could be elements at several indices that are all intersecting with the given point
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.
Thats right, index and (plain) coordinate based determination can both be wrong.
I'll remove the intersect optimization for now.
This case needs the generalized, will do that in another pr.
This case could be optimized using ranged lookup, but would need maximum radius/dimension on the axis direction of the elements to know how large range needs to be handled
.
Something like:
let range = determineMaxSizeOfElementsForAxis(axis);
const start = lookup(data, axis, position[axis] - range);
const end = lookup(data, axis, position[axis] + range);
const startIndex = start.loIndex || start.hiIndex;
const endIndex = end.hiIndex || end.loIndex;
for(let i = startIndex; i <= endIndex; ++i) {
handler(data[i], index, i);
}
Ok, ready for review again.
Timing: ~950ms (master is still ~750ms) Change mode to |
Reverse mode was not working, so fixed that. |
Generalize lookup
Revert generalization Revert getDistanceMetricForAxis relocation Private Add underscore Cache dimensions Remove optimization of getIntersectItems Revert "Cache dimensions" This reverts commit dc0252d. Conditionally use binarySearch for intersect mode Simplify lookup, add reverse support Intersect
Closes: #4246
master
pr