Skip to content

Commit

Permalink
feat: benchmark for causallyRealted function
Browse files Browse the repository at this point in the history
  • Loading branch information
JanLewDev committed Sep 6, 2024
1 parent 94fe07d commit 0d012d1
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 6 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"docs": "typedoc",
"proto-gen": "buf generate",
"release": "release-it",
"test": "vitest"
"test": "vitest",
"bench": "vitest bench"
},
"devDependencies": {
"@biomejs/biome": "^1.8.3",
Expand Down
50 changes: 45 additions & 5 deletions packages/object/src/hashgraph/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as crypto from "node:crypto";
import { BitSet } from "./bitset.js";

type Hash = string;
export type Hash = string;
export type Operation<T> = { type: string; value: T | null };

enum OperationType {
Expand Down Expand Up @@ -191,7 +191,7 @@ export class HashGraph<T> {
while (j < order.length) {
const moving = order[j];

if (!this.areCausallyRelated(anchor, moving)) {
if (!this.areCausallyRelatedUsingBitsets(anchor, moving)) {
const v1 = this.vertices.get(anchor);
const v2 = this.vertices.get(moving);
let action: ActionType;
Expand Down Expand Up @@ -233,12 +233,11 @@ export class HashGraph<T> {
return result;
}

// Time complexity: O(V), Space complexity: O(V)
areCausallyRelated(hash1: Hash, hash2: Hash): boolean {
// Amortised time complexity: O(1), Amortised space complexity: O(1)
areCausallyRelatedUsingBitsets(hash1: Hash, hash2: Hash): boolean {
if (!this.arePredecessorsFresh) {
this.topologicalSort();
}

const test1 =
this.reachablePredecessors
.get(hash1)
Expand All @@ -250,6 +249,47 @@ export class HashGraph<T> {
return test1 || test2;
}

// Time complexity: O(V), Space complexity: O(V)
areCausallyRelatedUsingBFS(hash1: Hash, hash2: Hash): boolean {
const visited = new Set<Hash>();
const stack = [hash1];

while (stack.length > 0) {
const current = stack.pop();
if (current === hash2) return true;
if (current === undefined) continue;
visited.add(current);

const vertex = this.vertices.get(current);
if (!vertex) continue;
for (const dep of vertex.dependencies) {
if (!visited.has(dep)) {
stack.push(dep);
}
}
}

visited.clear();
stack.push(hash2);

while (stack.length > 0) {
const current = stack.pop();
if (current === hash1) return true;
if (current === undefined) continue;
visited.add(current);

const vertex = this.vertices.get(current);
if (!vertex) continue;
for (const dep of vertex.dependencies) {
if (!visited.has(dep)) {
stack.push(dep);
}
}
}

return false;
}

// Time complexity: O(1), Space complexity: O(1)
getFrontier(): Hash[] {
return Array.from(this.frontier);
Expand Down
71 changes: 71 additions & 0 deletions packages/object/tests/causallyrelated.bench.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import test from "node:test";
import { beforeEach, bench, describe } from "vitest";
import { AddWinsSet } from "../../crdt/src/cros/AddWinsSet/index.js";
import {
type Hash,
type TopologyObject,
merge,
newTopologyObject,
} from "../src/index.js";

describe("AreCausallyDependent benchmark", async () => {
const samples = 100000;
const tests: Hash[][] = [];

const obj1 = await newTopologyObject("peer1", new AddWinsSet<number>());
const obj2 = await newTopologyObject("peer2", new AddWinsSet<number>());
const obj3 = await newTopologyObject("peer3", new AddWinsSet<number>());

const cro1 = obj1.cro as AddWinsSet<number>;
const cro2 = obj2.cro as AddWinsSet<number>;
const cro3 = obj3.cro as AddWinsSet<number>;

cro1.add(1);
merge(obj2, obj1.hashGraph.getAllVertices());

cro1.add(1);
cro1.remove(2);
cro2.remove(2);
cro2.add(2);

merge(obj3, obj1.hashGraph.getAllVertices());
cro3.add(3);
cro1.remove(1);

merge(obj1, obj2.hashGraph.getAllVertices());
cro1.remove(3);
cro2.remove(1);

merge(obj1, obj2.hashGraph.getAllVertices());
merge(obj1, obj3.hashGraph.getAllVertices());

const vertices = obj1.hashGraph.getAllVertices();
for (let i = 0; i < samples; i++) {
tests.push([
vertices[Math.floor(Math.random() * vertices.length)].hash,
vertices[Math.floor(Math.random() * vertices.length)].hash,
]);
}

bench("Causality check using BFS", async () => {
const cro1 = obj1.cro as AddWinsSet<number>;

for (let i = 0; i < samples; i++) {
const result = obj1.hashGraph.areCausallyRelatedUsingBFS(
tests[i][0],
tests[i][1],
);
}
});

bench("Causality check using Bitsets", async () => {
const cro1 = obj1.cro as AddWinsSet<number>;

for (let i = 0; i < samples; i++) {
const result = obj1.hashGraph.areCausallyRelatedUsingBitsets(
tests[i][0],
tests[i][1],
);
}
});
});

0 comments on commit 0d012d1

Please sign in to comment.