Skip to content

Commit

Permalink
Split Resource -> LinePoint Processing Across Multiple Frames (#1056)
Browse files Browse the repository at this point in the history
* Split line layer resource pre-processing across multiple frames

---------

Co-authored-by: Aaron Plave <[email protected]>
  • Loading branch information
jeffpamer and AaronPlave authored Jan 2, 2024
1 parent e1bf4cb commit c44edfa
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 17 deletions.
79 changes: 63 additions & 16 deletions src/components/timeline/LayerLine.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
export let yAxisId: number | null = null;
const dispatch = createEventDispatcher();
const WORK_TIME_THRESHOLD = 32; // ms to allow for processing time, beyond which remaining work will be split to a new frame
let canvas: HTMLCanvasElement;
let ctx: CanvasRenderingContext2D | null;
Expand All @@ -40,6 +41,9 @@
let drawPointsRequest: number;
let stateLinePlotYScale: ScalePoint<string>;
let yScale: ScaleLinear<number, number, never>;
let points: LinePoint[];
let tempPoints: LinePoint[];
let processingRequest: number;
$: canvasHeightDpr = drawHeight * dpr;
$: canvasWidthDpr = drawWidth * dpr;
Expand Down Expand Up @@ -67,7 +71,7 @@
$: onContextMenu(contextmenu);
$: onMousemove(mousemove);
$: onMouseout(mouseout);
$: points = resourcesToLinePoints(resources, pointRadius);
$: processResourcesToLinePoints(resources);
$: offscreenPoint = ctx && generateOffscreenPoint(lineColor, pointRadius);
onMount(() => {
Expand Down Expand Up @@ -183,64 +187,107 @@
}
}
function resourcesToLinePoints(resources: Resource[], radius: number): LinePoint[] {
const points: LinePoint[] = [];
let id = 0;
function processResourcesToLinePoints(resources: Resource[]) {
if (typeof window === 'undefined') {
return;
}
window.cancelAnimationFrame(processingRequest);
points = [];
tempPoints = [];
for (const resource of resources) {
processingRequest = window.requestAnimationFrame(() => resourcesToLinePoints(resources));
}
function resourcesToLinePoints(
resources: Resource[],
resourceStartIndex = 0,
valueStartIndex = 0,
startId = 0,
): void {
const startTime = performance.now();
let resourceIndex = resourceStartIndex;
let valueIndex = valueStartIndex;
let id = startId;
for (resourceIndex; resourceIndex < resources.length; ++resourceIndex) {
const resource = resources[resourceIndex];
const { name, schema, values } = resource;
if (schema.type === 'boolean') {
for (let i = 0; i < values.length; ++i) {
const value = values[i];
for (valueIndex; valueIndex < values.length; ++valueIndex) {
const value = values[valueIndex];
const { x, y: yBoolean } = value;
const y = yBoolean ? 1 : 0;
points.push({
tempPoints.push({
id: id++,
name,
radius,
type: 'line',
x,
y,
});
if (performance.now() - startTime > WORK_TIME_THRESHOLD) {
processingRequest = window.requestAnimationFrame(() =>
resourcesToLinePoints(resources, resourceIndex, valueIndex + 1, id),
);
return;
}
}
valueIndex = 0;
} else if (
schema.type === 'int' ||
schema.type === 'real' ||
(schema.type === 'struct' && schema?.items?.rate?.type === 'real' && schema?.items?.initial?.type === 'real')
) {
for (let i = 0; i < values.length; ++i) {
const value = values[i];
for (valueIndex; valueIndex < values.length; ++valueIndex) {
const value = values[valueIndex];
const { x } = value;
const y = value.y as number;
points.push({
tempPoints.push({
id: id++,
name,
radius,
type: 'line',
x,
y,
});
if (performance.now() - startTime > WORK_TIME_THRESHOLD) {
processingRequest = window.requestAnimationFrame(() =>
resourcesToLinePoints(resources, resourceIndex, valueIndex + 1, id),
);
return;
}
}
valueIndex = 0;
} else if (schema.type === 'string' || schema.type === 'variant') {
for (let i = 0; i < values.length; ++i) {
const value = values[i];
const { x } = value;
const y = value.y as number;
scaleDomain.add(value.y as string);
points.push({
tempPoints.push({
id: id++,
name,
radius: radius,
type: 'line',
x,
y,
});
if (performance.now() - startTime > WORK_TIME_THRESHOLD) {
processingRequest = window.requestAnimationFrame(() =>
resourcesToLinePoints(resources, resourceIndex, valueIndex + 1, id),
);
return;
}
}
valueIndex = 0;
}
}
return points;
points = tempPoints;
}
function generateOffscreenPoint(lineColor: string, radius: number): OffscreenCanvas | HTMLCanvasElement | null {
Expand Down
1 change: 0 additions & 1 deletion src/types/timeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ export interface LineLayer extends Layer {
}

export interface LinePoint extends Point {
radius: number;
y: number;
}

Expand Down

0 comments on commit c44edfa

Please sign in to comment.