Skip to content

Commit

Permalink
optimize finding next tick up or down
Browse files Browse the repository at this point in the history
  • Loading branch information
brianlund-wandb committed Dec 13, 2024
1 parent c964e3f commit 45a548c
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 7 deletions.
63 changes: 63 additions & 0 deletions weave-js/src/common/components/elements/SliderInput.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import {getClosestTick} from './SliderInput';

describe('getClosestTick', () => {
test('lower previous value returns next greater', () => {
let ticks = [...new Set([2, 4, 6, 8, 10])],
previous = 4,
val = 5;

expect(getClosestTick(ticks, val, previous)).toBe(6);
});
test('greater previous value returns next lesser', () => {
let ticks = [...new Set([2, 4, 6, 8, 10])],
previous = 4,
val = 3;
const actual = getClosestTick(ticks, val, previous);
expect(actual).toBe(2);
});
test('greater previous value returns next lesser, consecutive', () => {
let ticks = [...new Set([1, 2, 3, 4, 5, 6])],
previous = 4,
val = 3;
const actual = getClosestTick(ticks, val, previous);
expect(actual).toBe(3);
});
test('lower previous value returns next greater, consecutive', () => {
let ticks = [...new Set([1, 2, 3, 4, 5, 6])],
previous = 3,
val = 4;
const actual = getClosestTick(ticks, val, previous);
expect(actual).toBe(4);
});
test('lower previous value returns next greater, erratic', () => {
let ticks = [...new Set([1, 4, 5, 7, 9, 12])],
previous = 9,
val = 10;
const actual = getClosestTick(ticks, val, previous);
expect(actual).toBe(12);
});
test('greater previous value returns next lower, erratic', () => {
let ticks = [...new Set([1, 2, 5, 7, 9, 12])],
previous = 5,
val = 4;
const actual = getClosestTick(ticks, val, previous);
expect(actual).toBe(2);
});

// Modified logic, retaining for expected performance
test('large number of ticks', () => {
let ticks = [...new Set<number>()],
previous = 500000,
val = 500001;

for (let i = 0; i < 10000000; i += 2) {
ticks.push(i);
}
const start = Date.now();
const actual = getClosestTick(ticks, val, previous);
const end = Date.now();
const duration = end - start;
expect(actual).toBe(500002);
expect(duration).toBeLessThanOrEqual(1);
});
});
35 changes: 28 additions & 7 deletions weave-js/src/common/components/elements/SliderInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ const SliderInput: React.FC<SliderInputProps> = React.memo(
newVal = min;
}
if (ticks != null) {
newVal = getClosestTick(ticks, newVal);
newVal = getClosestTick(ticks, newVal, sliderValue);
}
setSliderValue(newVal);
onChangeDebounced(newVal);
Expand Down Expand Up @@ -172,17 +172,38 @@ const SliderInput: React.FC<SliderInputProps> = React.memo(

export default SliderInput;

function getClosestTick(ticks: number[], val: number): number {
export function getClosestTick(
ticks: number[],
val: number,
prev: number
): number {
let closest = val;
const increasing = val > prev;
let minDiff = Number.MAX_VALUE;

for (const tick of ticks) {
// Binary search for the closest tick
let left = 0;
let right = ticks.length - 1;

while (left <= right) {
const mid = Math.floor((left + right) / 2);
const tick = ticks[mid];
const diff = Math.abs(tick - val);
if (diff >= minDiff) {
break;

// Only update closest if the tick is in the right direction
if (
diff < minDiff &&
((increasing && tick >= val) || (!increasing && tick <= val))
) {
closest = tick;
minDiff = diff;
}

if (tick < val) {
left = mid + 1;
} else {
right = mid - 1;
}
closest = tick;
minDiff = diff;
}

return closest;
Expand Down

0 comments on commit 45a548c

Please sign in to comment.