From 180c5cba37321ca9a766f622ba70dda9762724ef Mon Sep 17 00:00:00 2001 From: draedful Date: Wed, 14 May 2025 14:52:17 +0300 Subject: [PATCH] chore: create story to reproduce issue --- .../issues/Issue86PerformanceDrop.stories.tsx | 160 ++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 src/stories/issues/Issue86PerformanceDrop.stories.tsx diff --git a/src/stories/issues/Issue86PerformanceDrop.stories.tsx b/src/stories/issues/Issue86PerformanceDrop.stories.tsx new file mode 100644 index 00000000..b979e2f9 --- /dev/null +++ b/src/stories/issues/Issue86PerformanceDrop.stories.tsx @@ -0,0 +1,160 @@ +import React, { useCallback, useEffect, useState } from "react"; + +import { Meta, StoryFn } from "@storybook/react"; +import groupBy from "lodash/groupBy"; + +import type { TBlock, TConnection } from "../../../src"; +import { BlockGroups, Group } from "../../../src/components/canvas/groups"; +import { GraphBlock, GraphCanvas, useGraph } from "../../../src/react-component"; + +const NUM_BLOCKS = 2000; +const SUBGRAPH_SIZE = 100; +const GROUP_SIZE = 50; + +function generateBlocks(count: number): TBlock[] { + const blocks: TBlock[] = []; + for (let i = 0; i < count; i++) { + blocks.push({ + id: "block-" + i, + name: "Block " + i, + x: (i % 20) * 150, + y: Math.floor(i / 20) * 100, + width: 100, + height: 50, + selected: false, + anchors: [], + is: "Block", + group: "group-" + Math.floor(i / GROUP_SIZE), + }); + } + return blocks; +} + +function generateConnections(blocks: TBlock[]): TConnection[] { + const connections: TConnection[] = []; + for (let i = 0; i < blocks.length - 1; i++) { + if (i % 2 !== 0) { + connections.push({ + id: "conn-" + i, + sourceBlockId: blocks[i].id, + targetBlockId: blocks[i + 1].id, + }); + } + } + return connections; +} + +const allBlocks = generateBlocks(NUM_BLOCKS); +const allConnections = generateConnections(allBlocks); +const subGraphBlocks = allBlocks.slice(0, SUBGRAPH_SIZE); + +const MyGroup = Group.define({ + style: { + background: "rgba(100, 100, 100, 0.1)", + border: "rgba(100, 100, 100, 0.3)", + borderWidth: 2, + selectedBackground: "rgba(100, 100, 100, 1)", + selectedBorder: "rgba(100, 100, 100, 1)", + }, +}); + +const GroupsLayer = BlockGroups.withBlockGrouping({ + groupingFn: (blocks) => groupBy(blocks, (block) => block.$state.value.group), + mapToGroups: (groupId, { rect }) => ({ + id: groupId, + rect, + component: MyGroup, + }), +}); + +const meta: Meta = { + title: "Issues/Issue 86 Performance Drop", + component: GraphCanvas, +}; +export default meta; + +const Template: StoryFn = () => { + const { graph } = useGraph({}); + const [renderTime, setRenderTime] = useState(null); + const [currentView, setCurrentView] = useState<"full" | "sub">("full"); + + useEffect(() => { + if (graph) { + const layer = graph.addLayer(GroupsLayer, { + draggable: true, + updateBlocksOnDrag: true, + }); + return () => { + layer.detachLayer(); + }; + } + }, [graph]); + + const showFullGraph = useCallback(() => { + if (graph) { + const startTime = performance.now(); + graph.setEntities({ blocks: allBlocks, connections: allConnections }); + const endTime = performance.now(); + setRenderTime(endTime - startTime); + setCurrentView("full"); + } + }, [graph]); + + const showSubGraph = useCallback(() => { + if (graph) { + const validSubGraphConnections = generateConnections(subGraphBlocks); + const startTime = performance.now(); + graph.setEntities({ blocks: subGraphBlocks, connections: validSubGraphConnections }); + const endTime = performance.now(); + setRenderTime(endTime - startTime); + setCurrentView("sub"); + } + }, [graph]); + + useEffect(() => { + if (graph) { + graph.start(); + showSubGraph(); + } + }, [graph]); + + const renderBlock = useCallback( + (g, block) => ( + + {block.name} + + ), + [] + ); + + return ( +
+
+ + + {renderTime !== null && ( + {`Last setEntities took: ${renderTime.toFixed(2)} ms`} + )} +

Current view: {currentView}

+

+ Instructions: +

    +
  1. Initially, the sub-graph is shown. Note the time.
  2. +
  3. Click "Show Full Graph". Note the time. This is expected to be slow.
  4. +
  5. Click "Show Sub-Graph" again.
  6. +
+

+
+
+ +
+
+ ); +}; + +export const PerformanceIssueReproduction = Template.bind({}); +PerformanceIssueReproduction.args = {};