From 84bcfa61d85ad7b2de896a9e6a24fd5e8ff1bd46 Mon Sep 17 00:00:00 2001 From: Max Richter Date: Wed, 20 Mar 2024 17:39:52 +0100 Subject: [PATCH] feat: improve loading times --- .../src/lib/components/BoxSelection.svelte | 2 +- frontend/src/lib/components/edges/Edge.svelte | 25 ++++------ .../src/lib/components/graph/Graph.svelte | 7 +-- .../src/lib/components/graph/GraphView.svelte | 3 +- frontend/src/lib/components/graph/stores.ts | 2 +- frontend/src/lib/components/node/Node.svelte | 6 +-- frontend/src/lib/graph-manager.ts | 46 +++++++++++++------ frontend/src/lib/graphs/grid.ts | 1 + frontend/src/lib/graphs/tree.ts | 6 ++- frontend/src/lib/runtime-executor.ts | 11 +---- frontend/src/lib/types/index.ts | 2 + frontend/src/routes/+page.svelte | 2 +- 12 files changed, 62 insertions(+), 51 deletions(-) diff --git a/frontend/src/lib/components/BoxSelection.svelte b/frontend/src/lib/components/BoxSelection.svelte index ec84641..a7a4fe9 100644 --- a/frontend/src/lib/components/BoxSelection.svelte +++ b/frontend/src/lib/components/BoxSelection.svelte @@ -24,7 +24,7 @@ .selection { width: 40px; height: 20px; - border: solid 0.2px white; + border: solid 0.2px rgba(200, 200, 200, 0.8); border-style: dashed; border-radius: 2px; } diff --git a/frontend/src/lib/components/edges/Edge.svelte b/frontend/src/lib/components/edges/Edge.svelte index c6ff08f..75f94ef 100644 --- a/frontend/src/lib/components/edges/Edge.svelte +++ b/frontend/src/lib/components/edges/Edge.svelte @@ -19,17 +19,11 @@ import { CubicBezierCurve } from "three/src/extras/curves/CubicBezierCurve.js"; import { Vector3 } from "three/src/math/Vector3.js"; import { Vector2 } from "three/src/math/Vector2.js"; - import { LineMaterial } from "three/examples/jsm/Addons.js"; export let from: { x: number; y: number }; export let to: { x: number; y: number }; - const samples = Math.max( - 5, - Math.floor( - Math.sqrt(Math.pow(to.x - from.x, 2) + Math.pow(to.y - from.y, 2)) / 2, - ), - ); + let samples = 5; const curve = new CubicBezierCurve( new Vector2(from.x, from.y), @@ -45,8 +39,6 @@ let mesh: Mesh; - const color = new Color(32 / 255, 32 / 255, 32 / 255); - export const update = function (force = false) { if (!force) { const new_x = from.x + to.x; @@ -60,18 +52,17 @@ const mid = new Vector2((from.x + to.x) / 2, (from.y + to.y) / 2); - // const length = Math.sqrt( - // Math.pow(to.x - from.x, 2) + Math.pow(to.y - from.y, 2), - // ); - // + const length = Math.floor( + Math.sqrt(Math.pow(to.x - from.x, 2) + Math.pow(to.y - from.y, 2)) / 4, + ); + samples = Math.min(Math.max(10, length), 100); curve.v0.set(from.x, from.y); curve.v1.set(mid.x, from.y); curve.v2.set(mid.x, to.y); curve.v3.set(to.x, to.y); + points = curve.getPoints(samples).map((p) => new Vector3(p.x, 0, p.y)); - // mesh.setGeometry(points); - // mesh.needsUpdate = true; }; update(); @@ -101,7 +92,9 @@ - + {#key samples} + + {/key} {/if} - + {#key $graphId} + + {/key} {:else if $status === "loading"} Loading {:else if $status === "error"} diff --git a/frontend/src/lib/components/graph/GraphView.svelte b/frontend/src/lib/components/graph/GraphView.svelte index ff19281..54e8dd9 100644 --- a/frontend/src/lib/components/graph/GraphView.svelte +++ b/frontend/src/lib/components/graph/GraphView.svelte @@ -78,6 +78,7 @@ width: 0px; height: 0px; transform: scale(calc(var(--cz) * 0.1)); - --input-opacity: calc((var(--cz) - 2) / 5); + display: var(--node-display, block); + opacity: calc((var(--cz) - 2) / 5); } diff --git a/frontend/src/lib/components/graph/stores.ts b/frontend/src/lib/components/graph/stores.ts index 82bc014..6744b29 100644 --- a/frontend/src/lib/components/graph/stores.ts +++ b/frontend/src/lib/components/graph/stores.ts @@ -4,7 +4,7 @@ import { writable, type Writable } from "svelte/store"; import { Color } from "three/src/math/Color.js"; export const activeNodeId: Writable = writable(-1); -export const selectedNodes: Writable | null> = writable(null); +export const selectedNodes: Writable | null> = writable(new Set()); export const activeSocket: Writable = writable(null); export const hoveredSocket: Writable = writable(null); diff --git a/frontend/src/lib/components/node/Node.svelte b/frontend/src/lib/components/node/Node.svelte index 1592aff..ac91e3d 100644 --- a/frontend/src/lib/components/node/Node.svelte +++ b/frontend/src/lib/components/node/Node.svelte @@ -68,7 +68,7 @@ uniforms={{ uColorBright: { value: colorBright }, uColorDark: { value: colorDark }, - uSelectedColor: { value: new Color("#f2be90") }, + uSelectedColor: { value: new Color("#9d5f28") }, uActiveColor: { value: new Color("white") }, uSelected: { value: false }, uActive: { value: false }, @@ -113,10 +113,8 @@ transform: translate3d(var(--nx), var(--ny), 0); z-index: 1; font-weight: 300; - display: var(--node-display, block); --stroke: var(--background-color-lighter); --stroke-width: 2px; - opacity: var(--input-opacity); } .node.active { @@ -125,7 +123,7 @@ } .node.selected { - --stroke: #f2be90; + --stroke: #9d5f28; --stroke-width: 1px; } diff --git a/frontend/src/lib/graph-manager.ts b/frontend/src/lib/graph-manager.ts index d2a9474..91a3063 100644 --- a/frontend/src/lib/graph-manager.ts +++ b/frontend/src/lib/graph-manager.ts @@ -3,12 +3,15 @@ import { type Graph, type Node, type Edge, type Socket, type NodeRegistry, type import { HistoryManager } from "./history-manager"; import * as templates from "./graphs"; import EventEmitter from "./helpers/EventEmitter"; +import throttle from "./helpers/throttle"; export class GraphManager extends EventEmitter<{ "save": Graph }> { status: Writable<"loading" | "idle" | "error"> = writable("loading"); + loaded = false; - graph: Graph = { nodes: [], edges: [] }; + graph: Graph = { id: 0, nodes: [], edges: [] }; + id = writable(0); private _nodes: Map = new Map(); nodes: Writable> = writable(new Map()); @@ -32,6 +35,7 @@ export class GraphManager extends EventEmitter<{ "save": Graph }> { } this.inputSockets.set(s); }); + this.execute = throttle(() => this._execute(), 100); } serialize(): Graph { @@ -42,11 +46,12 @@ export class GraphManager extends EventEmitter<{ "save": Graph }> { props: node.props, })); const edges = this._edges.map(edge => [edge[0].id, edge[1], edge[2].id, edge[3]]) as Graph["edges"]; - return { nodes, edges }; + return { id: this.graph.id, nodes, edges }; } - execute() { - if (!this.runtime["loaded"]) return; + execute() { } + _execute() { + if (this.loaded === false) return; const start = performance.now(); const result = this.runtime.execute(this.serialize()); const end = performance.now(); @@ -64,12 +69,11 @@ export class GraphManager extends EventEmitter<{ "save": Graph }> { return [node.id, node] })); - this.edges.set(graph.edges.map((edge) => { + const edges = graph.edges.map((edge) => { const from = nodes.get(edge[0]); const to = nodes.get(edge[2]); if (!from || !to) { - console.error("Edge references non-existing node"); - return; + throw new Error("Edge references non-existing node"); }; from.tmp = from.tmp || {}; from.tmp.children = from.tmp.children || []; @@ -77,19 +81,22 @@ export class GraphManager extends EventEmitter<{ "save": Graph }> { to.tmp = to.tmp || {}; to.tmp.parents = to.tmp.parents || []; to.tmp.parents.push(from); - return [from, edge[1], to, edge[3]] as const; + return [from, edge[1], to, edge[3]] as Edge; }) - .filter(Boolean) as unknown as [Node, number, Node, string][] - ); + this.edges.set(edges); this.nodes.set(nodes); } async load(graph: Graph) { + this.loaded = false; this.graph = graph; + const a = performance.now(); this.status.set("loading"); + this.id.set(graph.id); + const b = performance.now(); for (const node of this.graph.nodes) { const nodeType = this.nodeRegistry.getNode(node.type); if (!nodeType) { @@ -100,13 +107,24 @@ export class GraphManager extends EventEmitter<{ "save": Graph }> { node.tmp = node.tmp || {}; node.tmp.type = nodeType; } + const c = performance.now(); this._init(this.graph); - setTimeout(() => { - this.status.set("idle"); - this.save(); - }, 100) + const d = performance.now(); + + this.save(); + + const e = performance.now(); + + this.status.set("idle"); + + this.loaded = true; + const f = performance.now(); + requestAnimationFrame(() => { + console.log(`Loading took ${f - a}ms; a-b: ${b - a}ms; b-c: ${c - b}ms; c-d: ${d - c}ms; d-e: ${e - d}ms; e-f: ${f - e}ms`); + this.execute(); + }); } diff --git a/frontend/src/lib/graphs/grid.ts b/frontend/src/lib/graphs/grid.ts index 48c6536..c1e0f75 100644 --- a/frontend/src/lib/graphs/grid.ts +++ b/frontend/src/lib/graphs/grid.ts @@ -3,6 +3,7 @@ import type { Graph } from "$lib/types"; export function grid(width: number, height: number) { const graph: Graph = { + id: Math.floor(Math.random() * 100000), edges: [], nodes: [], }; diff --git a/frontend/src/lib/graphs/tree.ts b/frontend/src/lib/graphs/tree.ts index 9261eef..87690d2 100644 --- a/frontend/src/lib/graphs/tree.ts +++ b/frontend/src/lib/graphs/tree.ts @@ -47,6 +47,10 @@ export function tree(depth: number): Graph { } - return { nodes, edges }; + return { + id: Math.floor(Math.random() * 100000), + nodes, + edges + }; } diff --git a/frontend/src/lib/runtime-executor.ts b/frontend/src/lib/runtime-executor.ts index fb19406..f838eb8 100644 --- a/frontend/src/lib/runtime-executor.ts +++ b/frontend/src/lib/runtime-executor.ts @@ -1,14 +1,8 @@ -import type { Graph, Node, NodeRegistry, NodeType, RuntimeExecutor } from "./types"; +import type { Graph, NodeRegistry, NodeType, RuntimeExecutor } from "./types"; export class MemoryRuntimeExecutor implements RuntimeExecutor { - loaded = false; - - constructor(private registry: NodeRegistry) { - setTimeout(() => { - this.loaded = true; - }, 500); - } + constructor(private registry: NodeRegistry) { } private getNodeTypes(graph: Graph) { @@ -92,7 +86,6 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor { } execute(graph: Graph) { - if (!this.loaded) return; // Then we add some metadata to the graph const [outputNode, nodes] = this.addMetaData(graph); diff --git a/frontend/src/lib/types/index.ts b/frontend/src/lib/types/index.ts index 9cd14bf..077897a 100644 --- a/frontend/src/lib/types/index.ts +++ b/frontend/src/lib/types/index.ts @@ -7,6 +7,7 @@ export type Node = { props?: Record, tmp?: { depth?: number; + mesh?: any; parents?: Node[], children?: Node[], inputNodes?: Record @@ -58,6 +59,7 @@ export interface RuntimeExecutor { export type Edge = [Node, number, Node, string]; export type Graph = { + id: number; meta?: { title?: string; lastModified?: string; diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index abe0a47..712ac72 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -37,7 +37,7 @@