bbc / peaks.js

JavaScript UI component for interacting with audio waveforms
https://waveform.prototyping.bbc.co.uk
GNU Lesser General Public License v3.0
3.16k stars 277 forks source link

Can't memoize segments for sorting #425

Closed adi518 closed 2 years ago

adi518 commented 2 years ago

I have to memoize a sorted segments array. To do that efficiently, I need a clear indicator for when the array has updated, which means I need a timestamp field that gets updated each time a segment is added or removed to/from the array. I'd like to hear other ideas as well.

Meanwhile, I hacked it like so:

const originalAdd = peaksInstance.segments.add;
peaksInstance.segments.add = function (segments: SegmentAddOptions | SegmentAddOptions[]) {
  this.timestamp = Date.now();
  originalAdd.call(this, segments);
};

const originalRemove = peaksInstance.segments.remove;
peaksInstance.segments.remove = function (segment: Segment) {
  this.timestamp = Date.now();
  return originalRemove.call(this, segment);
};

And now I can do this:

const getPeaksSortedSegmentsMemo = memoizee((_timestamp: number, segments: Segments) =>
  sortBy((segment) => segment.startTime, segments)
);

function getPeaksSortedSegments() {
  const segments = getPeaks('main')?.segments.getSegments();
  const timestamp = getPeaks('main')?.segments.timestamp!;
  if (segments?.length) {
    return getPeaksSortedSegmentsMemo(timestamp, segments);
  } else {
    return segments;
  }
}
chrisn commented 2 years ago

Would you also want to update the timestamp if any of the segments properties are changed, e.g., startTime and endTime. Another possibility could be to use the segments.add, segments.remove, segments.update, segments.dragged events.

adi518 commented 2 years ago

Supposedly, you're right and it'd be prone to bugs otherwise. However, I just tested it with dragging some segments without adding or removing any and it still works as expected, so I guess the segments array still gets called with add/remove. Actually, how does Peaks maintain its array of segments? does it do it linearly?

chrisn commented 2 years ago

They're just stored internally in an array in the order that you add them. Dragging a segment doesn't change it's position in the array.

adi518 commented 2 years ago

Closing since it didn't really matter at the end of it. We manage a memoized and sorted source of truth which peaks reads from, so it's all good.