diff --git a/rust/crates/tidy-tree/Cargo.toml b/rust/crates/tidy-tree/Cargo.toml index c5e3221..5f68959 100644 --- a/rust/crates/tidy-tree/Cargo.toml +++ b/rust/crates/tidy-tree/Cargo.toml @@ -12,7 +12,3 @@ tinyset = "0.4.10" [dev-dependencies] rand = "0.8.5" -[profile.bench] -opt-level = 3 -overflow-checks = false - diff --git a/rust/crates/tidy-tree/benches/gen.rs b/rust/crates/tidy-tree/benches/gen.rs new file mode 100644 index 0000000..de39a86 --- /dev/null +++ b/rust/crates/tidy-tree/benches/gen.rs @@ -0,0 +1,39 @@ +use std::ptr::NonNull; + +use rand::prelude::*; +use tidy_tree::{geometry::Coord, Node}; + +pub fn gen_node(rng: &mut StdRng) -> Node { + Node { + id: rng.gen(), + width: rng.gen_range(5..50) as Coord, + height: rng.gen_range(5..50) as Coord, + x: 0., + y: 0., + relative_x: 0., + relative_y: 0., + bbox: Default::default(), + parent: None, + children: vec![], + tidy: None, + } +} + +pub fn gen_tree(rng: &mut StdRng, num: usize) -> Node { + let root = gen_node(rng); + let mut nodes: Vec> = vec![(&root).into()]; + let max_chosen_size = 100; + for _ in 0..num { + let parent_index = if nodes.len() < max_chosen_size { + rng.gen_range(0..nodes.len()) + } else { + rng.gen_range((nodes.len() - max_chosen_size)..nodes.len()) + }; + let parent = unsafe { nodes[parent_index].as_mut() }; + let node = gen_node(rng); + parent.append_child(node); + nodes.push(parent.children.last().unwrap().as_ref().into()); + } + + root +} diff --git a/rust/crates/tidy-tree/benches/layout.rs b/rust/crates/tidy-tree/benches/layout.rs new file mode 100644 index 0000000..ed957f8 --- /dev/null +++ b/rust/crates/tidy-tree/benches/layout.rs @@ -0,0 +1,31 @@ +use rand::{prelude::StdRng, SeedableRng}; +use tidy_tree::{BasicLayout, Layout, TidyLayout}; +mod gen; + +// #[test] +// fn tidy() { +// let mut rng = StdRng::seed_from_u64(1001); +// let mut tree = gen::gen_tree(&mut rng, 100_000); +// let layout = TidyLayout { +// parent_child_margin: 10., +// peer_margin: 10., +// }; + +// for _ in 0..10 { +// layout.layout(&mut tree); +// } +// } + +#[test] +fn basic() { + let mut rng = StdRng::seed_from_u64(1001); + let mut tree = gen::gen_tree(&mut rng, 100_000); + let layout = BasicLayout { + parent_child_margin: 10., + peer_margin: 10., + }; + + for _ in 0..1000 { + layout.layout(&mut tree); + } +} diff --git a/rust/crates/tidy-tree/tests/gen.rs b/rust/crates/tidy-tree/tests/gen.rs index de39a86..14f862a 100644 --- a/rust/crates/tidy-tree/tests/gen.rs +++ b/rust/crates/tidy-tree/tests/gen.rs @@ -22,7 +22,7 @@ pub fn gen_node(rng: &mut StdRng) -> Node { pub fn gen_tree(rng: &mut StdRng, num: usize) -> Node { let root = gen_node(rng); let mut nodes: Vec> = vec![(&root).into()]; - let max_chosen_size = 100; + let max_chosen_size = 1000000; for _ in 0..num { let parent_index = if nodes.len() < max_chosen_size { rng.gen_range(0..nodes.len()) diff --git a/src/TidyComponent.tsx b/src/TidyComponent.tsx index 2ec6063..09b7bf9 100644 --- a/src/TidyComponent.tsx +++ b/src/TidyComponent.tsx @@ -29,6 +29,7 @@ export const TidyComponent = ({ root, layoutType, updateTrigger }: Props) => { layoutRef.current = await TidyLayout.create(type); const innerRoot = layoutRef.current.set_root(root); layoutRef.current.layout(); + console.log(innerRoot); renderRef.current.init(innerRoot); }; diff --git a/src/stories/Tidy.stories.tsx b/src/stories/Tidy.stories.tsx index 197c171..7860f84 100644 --- a/src/stories/Tidy.stories.tsx +++ b/src/stories/Tidy.stories.tsx @@ -54,3 +54,47 @@ export const TidyLayout = ({ layoutType, ...props }: Props) => { ); }; + +export const Example0 = () => { + return ( + + ); +}; + +function node(width: number, height: number, children: Node[] = []): Node { + return { + x: 0, + y: 0, + width, + height, + children, + }; +} diff --git a/src/tidy.ts b/src/tidy.ts index 98f42e2..c9402c1 100644 --- a/src/tidy.ts +++ b/src/tidy.ts @@ -125,7 +125,7 @@ export class TidyLayout extends Disposable { height.push(node.height); parents.push(node.parentId ?? NULL_ID()); this.idToNode.set(node.id!, node as InnerNode); - for (const child of node.children) { + for (const child of node.children.concat().reverse()) { if (child.parentId == null) { child.parentId = node.id; } diff --git a/test/tidy.test.ts b/test/tidy.test.ts index 0278043..3dd551c 100644 --- a/test/tidy.test.ts +++ b/test/tidy.test.ts @@ -1,19 +1,34 @@ import { TidyLayout, initWasm, LayoutType } from '../src/tidy'; -import { describe, it } from 'vitest'; +import { beforeAll, expect, describe, it } from 'vitest'; import { createTree } from '../src/utils'; import { readFile } from 'fs/promises'; import { debugStrToTree } from '../src/stories/debugToTree'; import * as path from 'path'; describe('tidy', () => { - /** - * it takes 20ms to layout 100k nodes - */ - it('benchmark tidy', async () => { + beforeAll(async () => { const wasm = await readFile( path.join(__dirname, '../wasm_dist/wasm_bg.wasm'), ); await initWasm(wasm); + }); + + it('order', async () => { + const tidy = await TidyLayout.create(LayoutType.Tidy); + const root = createTree(100); + tidy.set_root(root); + tidy.layout(); + for (let i = 1; i < root.children.length; i++) { + expect(root.children[i].x - root.children[i].width / 2).toBeGreaterThan( + root.children[i - 1].x - root.children[i - 1].width / 2, + ); + } + }); + + /** + * it takes 20ms to layout 100k nodes + */ + it('benchmark tidy', async () => { const tidy = await TidyLayout.create(LayoutType.Tidy); const root = createTree(100_000); tidy.set_root(root); @@ -25,10 +40,6 @@ describe('tidy', () => { }); it('benchmark naive', async () => { - const wasm = await readFile( - path.join(__dirname, '../wasm_dist/wasm_bg.wasm'), - ); - await initWasm(wasm); const tidy = await TidyLayout.create(LayoutType.Basic); const root = createTree(100_000); tidy.set_root(root);