Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve performance for creating crdt.TreeNode #875

Merged
merged 1 commit into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions src/api/converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1064,16 +1064,12 @@ function fromTreeNodes(
}

const root = nodes[nodes.length - 1];
const depthTable = new Map<number, CRDTTreeNode>();
depthTable.set(pbTreeNodes[nodes.length - 1].depth, nodes[nodes.length - 1]);
for (let i = nodes.length - 2; i >= 0; i--) {
let parent: CRDTTreeNode;
for (let j = i + 1; j < nodes.length; j++) {
if (pbTreeNodes[i].depth - 1 === pbTreeNodes[j].depth) {
parent = nodes[j];
break;
}
}

const parent = depthTable.get(pbTreeNodes[i].depth - 1);
parent!.prepend(nodes[i]);
depthTable.set(pbTreeNodes[i].depth, nodes[i]);
}

root.updateDescendantsSize();
Expand Down Expand Up @@ -1593,6 +1589,8 @@ export const converter = {
toChangePack,
fromChangePack,
fromChanges,
toTreeNodes,
fromTreeNodes,
objectToBytes,
bytesToObject,
bytesToSnapshot,
Expand Down
60 changes: 49 additions & 11 deletions test/bench/tree.bench.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Document, Tree } from '@yorkie-js-sdk/src/yorkie';
import { converter, Document, Tree, TreeNode } from '@yorkie-js-sdk/src/yorkie';
import { MaxTimeTicket } from '@yorkie-js-sdk/src/document/time/ticket';
import { describe, bench, assert } from 'vitest';

const benchmarkTree = (size: number) => {
const benchmarkTreeEdit = (size: number) => {
const doc = new Document<{ tree: Tree }>('test-doc');

doc.update((root) => {
Expand All @@ -16,6 +16,7 @@ const benchmarkTree = (size: number) => {
}
});
};

const benchmarkTreeDeleteAll = (size: number) => {
const doc = new Document<{ tree: Tree }>('test-doc');

Expand All @@ -35,6 +36,7 @@ const benchmarkTreeDeleteAll = (size: number) => {
}, 'delete them');
assert.equal(doc.getRoot().tree.toXML(), `<doc><p></p></doc>`);
};

const benchmarkTreeSplitGC = (size: number) => {
const doc = new Document<{ tree: Tree }>('test-doc');

Expand All @@ -58,6 +60,7 @@ const benchmarkTreeSplitGC = (size: number) => {
const empty = 0;
assert.equal(empty, doc.getGarbageLen());
};

const benchmarkTreeEditGC = (size: number) => {
const doc = new Document<{ tree: Tree }>('test-doc');

Expand Down Expand Up @@ -85,27 +88,48 @@ const benchmarkTreeEditGC = (size: number) => {
assert.equal(empty, doc.getGarbageLen());
};

describe('tree', () => {
bench('tree 100', () => {
benchmarkTree(100);
const benchmarkTreeConvert = (size: number) => {
const doc = new Document<{ tree: Tree }>('test-doc');
doc.update((root) => {
const children: Array<TreeNode> = [];
for (let i = 1; i <= size; i++) {
children.push({ type: 'text', value: 'a' });
}

root.tree = new Tree({
type: 'doc',
children: [{ type: 'p', children: children }],
});
});

bench('tree 1000', () => {
benchmarkTree(1000);
const root = doc.getRoot().tree.getIndexTree().getRoot();
const pbTreeNodes = converter.toTreeNodes(root);
converter.fromTreeNodes(pbTreeNodes);
};

describe('tree.edit', () => {
bench('tree.edit 100', () => {
benchmarkTreeEdit(100);
});

bench('tree.edit 1000', () => {
benchmarkTreeEdit(1000);
});

bench('tree 100', () => {
benchmarkTree(100);
bench('tree.edit 100', () => {
benchmarkTreeEdit(100);
});

bench('tree 1000', () => {
benchmarkTree(1000);
bench('tree.edit 1000', () => {
benchmarkTreeEdit(1000);
});

bench('tree delete all 1000', () => {
benchmarkTreeDeleteAll(1000);
});
});

describe('tree GC', () => {
bench('tree split GC 100', () => {
benchmarkTreeSplitGC(100);
});
Expand All @@ -122,3 +146,17 @@ describe('tree', () => {
benchmarkTreeEditGC(1000);
});
});

describe('tree convert', () => {
bench('tree convert from/to Protobuf 10000', () => {
benchmarkTreeConvert(10000);
});

bench('tree convert from/to Protobuf 20000', () => {
benchmarkTreeConvert(20000);
});

bench('tree convert from/to Protobuf 30000', () => {
benchmarkTreeConvert(30000);
});
});
Loading