Skip to content

Commit

Permalink
Enhance the benchmark
Browse files Browse the repository at this point in the history
  • Loading branch information
devraymondsh committed Jan 8, 2024
1 parent e26d7b8 commit 7f38e26
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 135 deletions.
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,27 @@ JsMap:
┌─────────┬─────────────────┬────────────────────┬───────────────────┐
│ (index) │ totalLookupTime │ totalInsertionTime │ totalDeletionTime │
├─────────┼─────────────────┼────────────────────┼───────────────────┤
│ 0 │ '1112.18 ms' │ '1258.46 ms' │ '1272.44 ms' │
│ 1 │ '1103.26 ms' │ '1199.46 ms' │ '1281.72 ms' │
│ average │ '1107.72 ms' │ '1228.96 ms' │ '1277.08 ms' │
│ 0 │ '134.71 ms' │ '362.9 ms' '212.05 ms' │
│ 1 │ '140.82 ms' │ '149.01 ms' '217.53 ms' │
│ average │ '137.77 ms' │ '255.95 ms' '214.79 ms' │
└─────────┴─────────────────┴────────────────────┴───────────────────┘
Kivi:
┌─────────┬─────────────────┬────────────────────┬───────────────────┐
│ (index) │ totalLookupTime │ totalInsertionTime │ totalDeletionTime │
├─────────┼─────────────────┼────────────────────┼───────────────────┤
│ 0 │ '1350.07 ms' │ '559.04 ms' │ '1355.66 ms' │
│ 1 │ '1349.39 ms' │ '557.93 ms' │ '1346.2 ms' │
│ average │ '1349.73 ms' │ '558.49 ms' │ '1350.93 ms' │
│ 0 │ '916.68 ms' │ '225.9 ms' │ '976.8 ms'
│ 1 │ '907.01 ms' │ '217.65 ms' │ '1017.35 ms' │
│ average │ '911.84 ms' │ '221.78 ms' │ '997.08 ms' │
└─────────┴─────────────────┴────────────────────┴───────────────────┘
This table shows how much JsMap is faster than Kivi:
┌───────────┬─────────┐
│ (index) │ Values │
├───────────┼─────────┤
│ lookup │ '1.22x' │
│ insertion │ '0.45x' │
│ deletion │ '1.06x' │
│ lookup │ '6.62x' │
│ insertion │ '0.85x' │
│ deletion │ '4.64x' │
└───────────┴─────────┘
```

Expand Down
81 changes: 19 additions & 62 deletions bench/bench-with-builtin.js
Original file line number Diff line number Diff line change
@@ -1,62 +1,36 @@
import fs from "node:fs";
import path from "node:path";
import json from "big-json";
import { fileURLToPath } from "node:url";
import { Kivi } from "../src/drivers/js/index.js";
import { isBun } from "../src/drivers/js/runtime.js";
import { generateFakeData } from "./faker/generate.js";

const repeatBenchmark = 2;
const fakeDataJsonFile = "faker/data/data.json";
const dataJsonPath = path.resolve(
path.dirname(fileURLToPath(import.meta.url)),
fakeDataJsonFile
);
const data = generateFakeData();

const assert = (name, left, right) => {
if (left !== right) {
if (!left.equals(right)) {
throw new Error(
`Assertion '${name}' failed! Left was '${left}' and right was '${right}'.`
`Assertion '${name}' failed! Left was '${left.toString()}' and right was '${right.toString()}'.`
);
}
};
const resolveOnEmit = (event) => {
return new Promise(function (resolve, reject) {
try {
event.on("data", (data) => resolve(data));
} catch (e) {
reject(e);
}
});
};
const roundToTwoDecimal = (num) => +(Math.round(num + "e+2") + "e-2");

const benchmarkDeletion = (data, o) => {
const benchmarkDeletion = (data, o, keyidx) => {
const startingTime = performance.now();
for (const item of data) {
assert(
`${o.name} deletion`,
o.del(Buffer.from(item.key, "utf8")).toString(),
Buffer.from(item.value, "utf8").toString()
);
assert(`${o.name} deletion`, o.del(item[keyidx]), item.value);
}
return performance.now() - startingTime;
};
const benchmarkLookup = (data, o) => {
const benchmarkLookup = (data, o, keyidx) => {
const startingTime = performance.now();
for (const item of data) {
assert(
`${o.name} lookup`,
o.get(Buffer.from(item.key, "utf8")).toString(),
Buffer.from(item.value, "utf8").toString()
);
assert(`${o.name} deletion`, o.get(item[keyidx]), item.value);
}
return performance.now() - startingTime;
};
const benchmarkInsertion = (data, o) => {
const benchmarkInsertion = (data, o, keyidx) => {
const startingTime = performance.now();
for (const item of data) {
o.set(Buffer.from(item.key, "utf8"), Buffer.from(item.value, "utf8"));
o.set(item[keyidx], item.value);
}
return performance.now() - startingTime;
};
Expand Down Expand Up @@ -120,23 +94,6 @@ const logRatio = () => {
});
};

let data;
if (!fs.existsSync(dataJsonPath)) {
await generateFakeData();
}
console.log("Loading the data. Please be patient...");
if (!isBun()) {
const readStream = fs.createReadStream(dataJsonPath);
const parseStream = json.createParseStream();
readStream.pipe(parseStream);

data = await resolveOnEmit(parseStream);
} else {
const file = Bun.file(dataJsonPath);
data = await file.json();
}
let dataKeys = data.map((el) => el.key);

const builtinMapBenchmark = () => {
const durationArr = [];
let average = {
Expand All @@ -149,23 +106,23 @@ const builtinMapBenchmark = () => {
name: "JsMap",
map: new Map(),
get: function (k) {
return this.map.get(k.toString());
return this.map.get(k);
},
set: function (k, v) {
return this.map.set(k.toString(), v);
return this.map.set(k, v);
},
del: function (k) {
const v = this.map.get(k.toString());
this.map.delete(k.toString());
const v = this.map.get(k);
this.map.delete(k);
return v;
},
destroy: function () {
return this.map.clear();
},
};
const insertionDuration = benchmarkInsertion(data, o);
const lookupDuration = benchmarkLookup(data, o);
const deletionDuration = benchmarkDeletion(data, o);
const insertionDuration = benchmarkInsertion(data, o, "key");
const lookupDuration = benchmarkLookup(data, o, "key");
const deletionDuration = benchmarkDeletion(data, o, "key");
o.destroy();
durationArr.push({
iteration: i,
Expand Down Expand Up @@ -213,9 +170,9 @@ const kiviBenchmark = () => {
return this.map.destroy();
},
};
const insertionDuration = benchmarkInsertion(data, o);
const lookupDuration = benchmarkLookup(data, o);
const deletionDuration = benchmarkDeletion(data, o);
const insertionDuration = benchmarkInsertion(data, o, "kyb");
const lookupDuration = benchmarkLookup(data, o, "kyb");
const deletionDuration = benchmarkDeletion(data, o, "kyb");
o.destroy();
durationArr.push({
iteration: i,
Expand Down
90 changes: 53 additions & 37 deletions bench/faker/generate.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,58 @@
import fs from "node:fs";
import path from "path";
import json from "big-json";
import { fileURLToPath } from "url";
import { faker } from "@faker-js/faker";

const count = 1_000_000;

export const generateFakeData = () =>
new Promise((resolve) => {
console.log("Generating fake data for the benchmark...");

const arr = [];
for (let i = 0; i < count; i++) {
arr.push({
key: faker.string.uuid() + "_" + faker.person.fullName(),
value: JSON.stringify({
bio: faker.person.bio(),
gender: faker.person.gender(),
jobArea: faker.person.jobArea(),
jobTitle: faker.person.jobTitle(),
jobType: faker.person.jobType(),
name: faker.person.fullName(),
}),
});
if (i % (count / 10) == 0 && i != 0) {
console.log((i / count) * 100 + "%");
}
const genRandomNum = (min, max) => {
return Math.random() * (max - min) + min;
};
const genRandomStr = function (length) {
let result = "";
const characters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const charactersLength = characters.length;
let counter = 0;
while (counter < length) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
counter += 1;
}
return result;
};
function genUUID() {
// Public Domain/MIT
var d = new Date().getTime(); //Timestamp
var d2 =
(typeof performance !== "undefined" &&
performance.now &&
performance.now() * 1000) ||
0; //Time in microseconds since page-load or 0 if unsupported
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
var r = Math.random() * 16; //random number between 0 and 16
if (d > 0) {
//Use timestamp until depleted
r = (d + r) % 16 | 0;
d = Math.floor(d / 16);
} else {
//Use microseconds since page-load if supported
r = (d2 + r) % 16 | 0;
d2 = Math.floor(d2 / 16);
}
return (c === "x" ? r : (r & 0x3) | 0x8).toString(16);
});
}

export const generateFakeData = () => {
console.log("Generating fake data for the benchmark...");

const dataJsonPath = path.resolve(
path.dirname(fileURLToPath(import.meta.url)),
"data/data.json"
);
console.log("Writing the data. Please be patient.");
const writeStream = fs.createWriteStream(dataJsonPath);
const stringifyStream = json.createStringifyStream({
body: arr,
const data = [];
for (let i = 0; i <= count; i++) {
const key = genRandomStr(genRandomNum(2, 150)) + genUUID();
data.push({
key,
kyb: Buffer.from(key, "utf8"),
value: Buffer.from(genRandomStr(genRandomNum(2, 500)), "utf8"),
});
const pipe = stringifyStream.pipe(writeStream);
pipe.on("finish", () => resolve());
});
if (i % (count / 10) == 0 && i != 0) {
console.log((i / count) * 100 + "%");
}
}

return data;
};
5 changes: 1 addition & 4 deletions bench/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,5 @@
},
"author": "",
"license": "ISC",
"dependencies": {
"big-json": "^3.2.0",
"@faker-js/faker": "^8.0.2"
}
"dependencies": {}
}
24 changes: 1 addition & 23 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -134,24 +134,6 @@ inline fn run_npm_command(
}
}

inline fn run_npm_install(
b: *std.Build,
comptime dir: anytype,
dependency_step: ?*std.Build.Step,
runner_step: ?*std.Build.Step,
) std.Build.Step {
const syscommand = b.addSystemCommand(&[2][]const u8{ "pnpm", "install" });
syscommand.cwd = get_lazypath(dir);
if (dependency_step) |step| {
syscommand.step.dependOn(step);
}
if (runner_step != null) {
runner_step.?.dependOn(&syscommand.step);
}

return syscommand.step;
}

pub fn build(b: *std.Build) !void {
optimize = b.standardOptimizeOption(.{});
resolved_target = b.standardTargetOptions(.{});
Expand Down Expand Up @@ -250,10 +232,6 @@ pub fn build(b: *std.Build) !void {
test_step,
);

// Installs benchmark dependencies
const bench_dep_install_step = b.step("bench-install", "Installs benchmark dependencies");
_ = run_npm_install(b, "bench", null, bench_dep_install_step);

// Benchmarks Kivi
const bench_step = b.step("bench", "Benchmarks kivi");
_ = run_npm_command(
Expand All @@ -264,7 +242,7 @@ pub fn build(b: *std.Build) !void {
// "deno-bench",
// "bun-bench",
},
.{ bench_dep_install_step, drivers_build_step },
.{drivers_build_step},
bench_step,
);
}

0 comments on commit 7f38e26

Please sign in to comment.