mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-16 19:57:52 +01:00
core: optimize bson objectid generation & add benchmarks
This commit is contained in:
37
packages/core/__benches__/objectid.bench.ts
Normal file
37
packages/core/__benches__/objectid.bench.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
This file is part of the Notesnook project (https://notesnook.com/)
|
||||||
|
|
||||||
|
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { bench, describe } from "vitest";
|
||||||
|
import { createObjectId } from "../src/utils/object-id";
|
||||||
|
import boid from "bson-objectid";
|
||||||
|
import { nanoid } from "nanoid";
|
||||||
|
|
||||||
|
describe("objectid", async () => {
|
||||||
|
bench("custom", () => {
|
||||||
|
createObjectId();
|
||||||
|
});
|
||||||
|
|
||||||
|
bench("bson-objectid", () => {
|
||||||
|
boid().toHexString();
|
||||||
|
});
|
||||||
|
|
||||||
|
bench("nanoid", () => {
|
||||||
|
nanoid(32);
|
||||||
|
});
|
||||||
|
});
|
||||||
26
packages/core/package-lock.json
generated
26
packages/core/package-lock.json
generated
@@ -44,6 +44,7 @@
|
|||||||
"@vitest/coverage-v8": "^0.34.1",
|
"@vitest/coverage-v8": "^0.34.1",
|
||||||
"abortcontroller-polyfill": "^1.7.3",
|
"abortcontroller-polyfill": "^1.7.3",
|
||||||
"better-sqlite3": "^8.6.0",
|
"better-sqlite3": "^8.6.0",
|
||||||
|
"bson-objectid": "^2.0.4",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"dotenv": "^16.0.1",
|
"dotenv": "^16.0.1",
|
||||||
"event-source-polyfill": "^1.0.31",
|
"event-source-polyfill": "^1.0.31",
|
||||||
@@ -52,6 +53,7 @@
|
|||||||
"isomorphic-fetch": "^3.0.0",
|
"isomorphic-fetch": "^3.0.0",
|
||||||
"jsdom": "^22.1.0",
|
"jsdom": "^22.1.0",
|
||||||
"mockdate": "^3.0.5",
|
"mockdate": "^3.0.5",
|
||||||
|
"nanoid": "^5.0.1",
|
||||||
"otplib": "^12.0.1",
|
"otplib": "^12.0.1",
|
||||||
"refractor": "^4.8.1",
|
"refractor": "^4.8.1",
|
||||||
"vitest": "^0.34.1",
|
"vitest": "^0.34.1",
|
||||||
@@ -2526,6 +2528,12 @@
|
|||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/bson-objectid": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/bson-objectid/-/bson-objectid-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-vgnKAUzcDoa+AeyYwXCoHyF2q6u/8H46dxu5JN+4/TZeq/Dlinn0K6GvxsCLb3LHUJl0m/TLiEK31kUwtgocMQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/buffer": {
|
"node_modules/buffer": {
|
||||||
"version": "5.7.1",
|
"version": "5.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||||
@@ -3612,6 +3620,24 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/nanoid": {
|
||||||
|
"version": "5.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.5.tgz",
|
||||||
|
"integrity": "sha512-/Veqm+QKsyMY3kqi4faWplnY1u+VuKO3dD2binyPIybP31DRO29bPF+1mszgLnrR2KqSLceFLBNw0zmvDzN1QQ==",
|
||||||
|
"dev": true,
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/ai"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bin": {
|
||||||
|
"nanoid": "bin/nanoid.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^18 || >=20"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/napi-build-utils": {
|
"node_modules/napi-build-utils": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
"@vitest/coverage-v8": "^0.34.1",
|
"@vitest/coverage-v8": "^0.34.1",
|
||||||
"abortcontroller-polyfill": "^1.7.3",
|
"abortcontroller-polyfill": "^1.7.3",
|
||||||
"better-sqlite3": "^8.6.0",
|
"better-sqlite3": "^8.6.0",
|
||||||
|
"bson-objectid": "^2.0.4",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"dotenv": "^16.0.1",
|
"dotenv": "^16.0.1",
|
||||||
"event-source-polyfill": "^1.0.31",
|
"event-source-polyfill": "^1.0.31",
|
||||||
@@ -29,6 +30,7 @@
|
|||||||
"isomorphic-fetch": "^3.0.0",
|
"isomorphic-fetch": "^3.0.0",
|
||||||
"jsdom": "^22.1.0",
|
"jsdom": "^22.1.0",
|
||||||
"mockdate": "^3.0.5",
|
"mockdate": "^3.0.5",
|
||||||
|
"nanoid": "^5.0.1",
|
||||||
"otplib": "^12.0.1",
|
"otplib": "^12.0.1",
|
||||||
"refractor": "^4.8.1",
|
"refractor": "^4.8.1",
|
||||||
"vitest": "^0.34.1",
|
"vitest": "^0.34.1",
|
||||||
|
|||||||
@@ -17,35 +17,16 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { BufferPool } from "./buffer-pool";
|
|
||||||
import { randomBytes, randomInt } from "./random";
|
import { randomBytes, randomInt } from "./random";
|
||||||
|
|
||||||
const PROCESS_UNIQUE = randomBytes(5);
|
const PROCESS_UNIQUE = randomBytes(5).toString("hex");
|
||||||
let index = ~~(randomInt() * 0xffffff);
|
let index = ~~(randomInt() * 0xffffff);
|
||||||
|
|
||||||
const objectIdPool = new BufferPool(12);
|
|
||||||
export function createObjectId(date = Date.now()): string {
|
export function createObjectId(date = Date.now()): string {
|
||||||
const buffer = objectIdPool.alloc();
|
index++;
|
||||||
index = (index + 1) % 0xffffff;
|
const time = Math.floor(date / 1000);
|
||||||
|
return time.toString(16) + PROCESS_UNIQUE + swap16(index).toString(16);
|
||||||
const time = ~~(date / 1000);
|
}
|
||||||
|
|
||||||
// 4-byte timestamp
|
function swap16(val: number) {
|
||||||
new DataView(buffer.buffer, 0, 4).setUint32(0, time);
|
return ((val & 0xff) << 16) | (val & 0xff00) | ((val >> 16) & 0xff);
|
||||||
|
|
||||||
// 5-byte process unique
|
|
||||||
buffer[4] = PROCESS_UNIQUE[0];
|
|
||||||
buffer[5] = PROCESS_UNIQUE[1];
|
|
||||||
buffer[6] = PROCESS_UNIQUE[2];
|
|
||||||
buffer[7] = PROCESS_UNIQUE[3];
|
|
||||||
buffer[8] = PROCESS_UNIQUE[4];
|
|
||||||
|
|
||||||
// 3-byte counter
|
|
||||||
buffer[11] = index & 0xff;
|
|
||||||
buffer[10] = (index >> 8) & 0xff;
|
|
||||||
buffer[9] = (index >> 16) & 0xff;
|
|
||||||
|
|
||||||
const objectId = buffer.toString("hex");
|
|
||||||
objectIdPool.free(buffer);
|
|
||||||
return objectId;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export function randomBytes(size: number) {
|
export function randomBytes(size: number): Buffer {
|
||||||
if (!globalThis.crypto || !crypto)
|
if (!globalThis.crypto || !crypto)
|
||||||
throw new Error("Crypto is not supported on this platform.");
|
throw new Error("Crypto is not supported on this platform.");
|
||||||
if ("randomBytes" in crypto && typeof crypto.randomBytes === "function")
|
if ("randomBytes" in crypto && typeof crypto.randomBytes === "function")
|
||||||
@@ -34,8 +34,5 @@ export function randomBytes(size: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function randomInt() {
|
export function randomInt() {
|
||||||
const randomBuffer = randomBytes(1);
|
return randomBytes(4).readInt32BE();
|
||||||
const randomNumber = randomBuffer[0] / 0xff; // / (0xffffffff + 1);
|
|
||||||
|
|
||||||
return Math.floor(randomNumber * 0xffffff);
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user