@offlinejs/benchmarks 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,30 @@
1
+ import { StorageAdapter, EntityRecord } from '@offlinejs/types';
2
+
3
+ interface BenchmarkResult {
4
+ durationMs: number;
5
+ name: string;
6
+ records: number;
7
+ throughputPerSecond?: number;
8
+ }
9
+ interface AdapterBenchmarkOptions {
10
+ collection?: string;
11
+ records?: number;
12
+ storage: StorageAdapter;
13
+ }
14
+ interface BenchmarkSuiteResult {
15
+ find: BenchmarkResult;
16
+ indexedFind?: BenchmarkResult;
17
+ writes: BenchmarkResult;
18
+ }
19
+ declare const createBenchmarkRecord: (index: number) => EntityRecord;
20
+ declare const benchmarkAdapterWrites: (options: AdapterBenchmarkOptions) => Promise<BenchmarkResult>;
21
+ declare const benchmarkAdapterBatchWrites: (options: AdapterBenchmarkOptions & {
22
+ batchSize?: number;
23
+ }) => Promise<BenchmarkResult>;
24
+ declare const benchmarkAdapterFind: (options: AdapterBenchmarkOptions) => Promise<BenchmarkResult>;
25
+ declare const benchmarkIndexedFind: (options: AdapterBenchmarkOptions) => Promise<BenchmarkResult>;
26
+ /** Seed + write/find suite sized for 100k-record adapter comparisons. */
27
+ declare const runAdapterBenchmarkSuite: (options: AdapterBenchmarkOptions) => Promise<BenchmarkSuiteResult>;
28
+ declare const formatBenchmarkResult: (result: BenchmarkResult) => string;
29
+
30
+ export { type AdapterBenchmarkOptions, type BenchmarkResult, type BenchmarkSuiteResult, benchmarkAdapterBatchWrites, benchmarkAdapterFind, benchmarkAdapterWrites, benchmarkIndexedFind, createBenchmarkRecord, formatBenchmarkResult, runAdapterBenchmarkSuite };
package/dist/index.js ADDED
@@ -0,0 +1,81 @@
1
+ // src/index.ts
2
+ var createBenchmarkRecord = (index) => ({
3
+ id: `record_${index}`,
4
+ createdAt: index,
5
+ group: index % 2 === 0 ? "even" : "odd",
6
+ title: `Benchmark record ${index}`
7
+ });
8
+ var benchmarkAdapterWrites = async (options) => {
9
+ const records = options.records ?? 1e5;
10
+ const collection = options.collection ?? "benchmark";
11
+ const startedAt = performance.now();
12
+ for (let index = 0; index < records; index += 1) {
13
+ await options.storage.set(collection, createBenchmarkRecord(index));
14
+ }
15
+ return toResult(`${options.storage.name}:writes`, records, startedAt);
16
+ };
17
+ var benchmarkAdapterBatchWrites = async (options) => {
18
+ const records = options.records ?? 1e5;
19
+ const collection = options.collection ?? "benchmark";
20
+ const batchSize = options.batchSize ?? 500;
21
+ const startedAt = performance.now();
22
+ for (let index = 0; index < records; index += batchSize) {
23
+ const batch = Array.from(
24
+ { length: Math.min(batchSize, records - index) },
25
+ (_, offset) => options.storage.set(collection, createBenchmarkRecord(index + offset))
26
+ );
27
+ await Promise.all(batch);
28
+ }
29
+ return toResult(`${options.storage.name}:batch-writes`, records, startedAt);
30
+ };
31
+ var benchmarkAdapterFind = async (options) => {
32
+ const collection = options.collection ?? "benchmark";
33
+ const startedAt = performance.now();
34
+ const records = await options.storage.find(collection, {
35
+ filters: { group: "even" },
36
+ limit: 100,
37
+ orderBy: "createdAt",
38
+ sort: "desc"
39
+ });
40
+ return toResult(`${options.storage.name}:find`, records.length, startedAt);
41
+ };
42
+ var benchmarkIndexedFind = async (options) => {
43
+ const collection = options.collection ?? "benchmark";
44
+ const storage = options.storage;
45
+ if (typeof storage.createIndex === "function") {
46
+ await storage.createIndex({
47
+ collection,
48
+ fields: ["group"],
49
+ name: "benchmark_group"
50
+ });
51
+ }
52
+ const startedAt = performance.now();
53
+ const records = await options.storage.find(collection, {
54
+ filters: { group: "even" },
55
+ limit: 100
56
+ });
57
+ return toResult(`${options.storage.name}:indexed-find`, records.length, startedAt);
58
+ };
59
+ var runAdapterBenchmarkSuite = async (options) => {
60
+ const writes = await benchmarkAdapterWrites(options);
61
+ const find = await benchmarkAdapterFind(options);
62
+ const indexedFind = await benchmarkIndexedFind(options);
63
+ return { find, indexedFind, writes };
64
+ };
65
+ var formatBenchmarkResult = (result) => {
66
+ const throughput = result.throughputPerSecond === void 0 ? "" : ` (${result.throughputPerSecond.toFixed(0)} ops/s)`;
67
+ return `${result.name}: ${result.records} records in ${result.durationMs.toFixed(2)}ms${throughput}`;
68
+ };
69
+ var toResult = (name, records, startedAt) => {
70
+ const durationMs = performance.now() - startedAt;
71
+ return {
72
+ durationMs,
73
+ name,
74
+ records,
75
+ ...durationMs > 0 ? { throughputPerSecond: records / durationMs * 1e3 } : {}
76
+ };
77
+ };
78
+
79
+ export { benchmarkAdapterBatchWrites, benchmarkAdapterFind, benchmarkAdapterWrites, benchmarkIndexedFind, createBenchmarkRecord, formatBenchmarkResult, runAdapterBenchmarkSuite };
80
+ //# sourceMappingURL=index.js.map
81
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";AAqBO,IAAM,qBAAA,GAAwB,CAAC,KAAA,MAAiC;AAAA,EACrE,EAAA,EAAI,UAAU,KAAK,CAAA,CAAA;AAAA,EACnB,SAAA,EAAW,KAAA;AAAA,EACX,KAAA,EAAO,KAAA,GAAQ,CAAA,KAAM,CAAA,GAAI,MAAA,GAAS,KAAA;AAAA,EAClC,KAAA,EAAO,oBAAoB,KAAK,CAAA;AAClC,CAAA;AAEO,IAAM,sBAAA,GAAyB,OACpC,OAAA,KAC6B;AAC7B,EAAA,MAAM,OAAA,GAAU,QAAQ,OAAA,IAAW,GAAA;AACnC,EAAA,MAAM,UAAA,GAAa,QAAQ,UAAA,IAAc,WAAA;AACzC,EAAA,MAAM,SAAA,GAAY,YAAY,GAAA,EAAI;AAElC,EAAA,KAAA,IAAS,KAAA,GAAQ,CAAA,EAAG,KAAA,GAAQ,OAAA,EAAS,SAAS,CAAA,EAAG;AAC/C,IAAA,MAAM,QAAQ,OAAA,CAAQ,GAAA,CAAI,UAAA,EAAY,qBAAA,CAAsB,KAAK,CAAC,CAAA;AAAA,EACpE;AAEA,EAAA,OAAO,SAAS,CAAA,EAAG,OAAA,CAAQ,QAAQ,IAAI,CAAA,OAAA,CAAA,EAAW,SAAS,SAAS,CAAA;AACtE;AAEO,IAAM,2BAAA,GAA8B,OACzC,OAAA,KAC6B;AAC7B,EAAA,MAAM,OAAA,GAAU,QAAQ,OAAA,IAAW,GAAA;AACnC,EAAA,MAAM,UAAA,GAAa,QAAQ,UAAA,IAAc,WAAA;AACzC,EAAA,MAAM,SAAA,GAAY,QAAQ,SAAA,IAAa,GAAA;AACvC,EAAA,MAAM,SAAA,GAAY,YAAY,GAAA,EAAI;AAElC,EAAA,KAAA,IAAS,KAAA,GAAQ,CAAA,EAAG,KAAA,GAAQ,OAAA,EAAS,SAAS,SAAA,EAAW;AACvD,IAAA,MAAM,QAAQ,KAAA,CAAM,IAAA;AAAA,MAAK,EAAE,MAAA,EAAQ,IAAA,CAAK,IAAI,SAAA,EAAW,OAAA,GAAU,KAAK,CAAA,EAAE;AAAA,MAAG,CAAC,CAAA,EAAG,MAAA,KAC7E,OAAA,CAAQ,OAAA,CAAQ,IAAI,UAAA,EAAY,qBAAA,CAAsB,KAAA,GAAQ,MAAM,CAAC;AAAA,KACvE;AACA,IAAA,MAAM,OAAA,CAAQ,IAAI,KAAK,CAAA;AAAA,EACzB;AAEA,EAAA,OAAO,SAAS,CAAA,EAAG,OAAA,CAAQ,QAAQ,IAAI,CAAA,aAAA,CAAA,EAAiB,SAAS,SAAS,CAAA;AAC5E;AAEO,IAAM,oBAAA,GAAuB,OAClC,OAAA,KAC6B;AAC7B,EAAA,MAAM,UAAA,GAAa,QAAQ,UAAA,IAAc,WAAA;AACzC,EAAA,MAAM,SAAA,GAAY,YAAY,GAAA,EAAI;AAClC,EAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,OAAA,CAAQ,KAAK,UAAA,EAAY;AAAA,IACrD,OAAA,EAAS,EAAE,KAAA,EAAO,MAAA,EAAO;AAAA,IACzB,KAAA,EAAO,GAAA;AAAA,IACP,OAAA,EAAS,WAAA;AAAA,IACT,IAAA,EAAM;AAAA,GACP,CAAA;AAED,EAAA,OAAO,QAAA,CAAS,GAAG,OAAA,CAAQ,OAAA,CAAQ,IAAI,CAAA,KAAA,CAAA,EAAS,OAAA,CAAQ,QAAQ,SAAS,CAAA;AAC3E;AAEO,IAAM,oBAAA,GAAuB,OAClC,OAAA,KAC6B;AAC7B,EAAA,MAAM,UAAA,GAAa,QAAQ,UAAA,IAAc,WAAA;AACzC,EAAA,MAAM,UAAU,OAAA,CAAQ,OAAA;AAExB,EAAA,IAAI,OAAO,OAAA,CAAQ,WAAA,KAAgB,UAAA,EAAY;AAC7C,IAAA,MAAM,QAAQ,WAAA,CAAY;AAAA,MACxB,UAAA;AAAA,MACA,MAAA,EAAQ,CAAC,OAAO,CAAA;AAAA,MAChB,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AAEA,EAAA,MAAM,SAAA,GAAY,YAAY,GAAA,EAAI;AAClC,EAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,OAAA,CAAQ,KAAK,UAAA,EAAY;AAAA,IACrD,OAAA,EAAS,EAAE,KAAA,EAAO,MAAA,EAAO;AAAA,IACzB,KAAA,EAAO;AAAA,GACR,CAAA;AAED,EAAA,OAAO,QAAA,CAAS,GAAG,OAAA,CAAQ,OAAA,CAAQ,IAAI,CAAA,aAAA,CAAA,EAAiB,OAAA,CAAQ,QAAQ,SAAS,CAAA;AACnF;AAGO,IAAM,wBAAA,GAA2B,OACtC,OAAA,KACkC;AAClC,EAAA,MAAM,MAAA,GAAS,MAAM,sBAAA,CAAuB,OAAO,CAAA;AACnD,EAAA,MAAM,IAAA,GAAO,MAAM,oBAAA,CAAqB,OAAO,CAAA;AAC/C,EAAA,MAAM,WAAA,GAAc,MAAM,oBAAA,CAAqB,OAAO,CAAA;AAEtD,EAAA,OAAO,EAAE,IAAA,EAAM,WAAA,EAAa,MAAA,EAAO;AACrC;AAEO,IAAM,qBAAA,GAAwB,CAAC,MAAA,KAAoC;AACxE,EAAA,MAAM,UAAA,GACJ,MAAA,CAAO,mBAAA,KAAwB,MAAA,GAC3B,EAAA,GACA,KAAK,MAAA,CAAO,mBAAA,CAAoB,OAAA,CAAQ,CAAC,CAAC,CAAA,OAAA,CAAA;AAChD,EAAA,OAAO,CAAA,EAAG,MAAA,CAAO,IAAI,CAAA,EAAA,EAAK,MAAA,CAAO,OAAO,CAAA,YAAA,EAAe,MAAA,CAAO,UAAA,CAAW,OAAA,CAAQ,CAAC,CAAC,KAAK,UAAU,CAAA,CAAA;AACpG;AAEA,IAAM,QAAA,GAAW,CAAC,IAAA,EAAc,OAAA,EAAiB,SAAA,KAAuC;AACtF,EAAA,MAAM,UAAA,GAAa,WAAA,CAAY,GAAA,EAAI,GAAI,SAAA;AACvC,EAAA,OAAO;AAAA,IACL,UAAA;AAAA,IACA,IAAA;AAAA,IACA,OAAA;AAAA,IACA,GAAI,aAAa,CAAA,GAAI,EAAE,qBAAsB,OAAA,GAAU,UAAA,GAAc,GAAA,EAAK,GAAI;AAAC,GACjF;AACF,CAAA","file":"index.js","sourcesContent":["import type { EntityRecord, IndexableStorageAdapter, StorageAdapter } from \"@offlinejs/types\";\n\nexport interface BenchmarkResult {\n durationMs: number;\n name: string;\n records: number;\n throughputPerSecond?: number;\n}\n\nexport interface AdapterBenchmarkOptions {\n collection?: string;\n records?: number;\n storage: StorageAdapter;\n}\n\nexport interface BenchmarkSuiteResult {\n find: BenchmarkResult;\n indexedFind?: BenchmarkResult;\n writes: BenchmarkResult;\n}\n\nexport const createBenchmarkRecord = (index: number): EntityRecord => ({\n id: `record_${index}`,\n createdAt: index,\n group: index % 2 === 0 ? \"even\" : \"odd\",\n title: `Benchmark record ${index}`\n});\n\nexport const benchmarkAdapterWrites = async (\n options: AdapterBenchmarkOptions\n): Promise<BenchmarkResult> => {\n const records = options.records ?? 100_000;\n const collection = options.collection ?? \"benchmark\";\n const startedAt = performance.now();\n\n for (let index = 0; index < records; index += 1) {\n await options.storage.set(collection, createBenchmarkRecord(index));\n }\n\n return toResult(`${options.storage.name}:writes`, records, startedAt);\n};\n\nexport const benchmarkAdapterBatchWrites = async (\n options: AdapterBenchmarkOptions & { batchSize?: number }\n): Promise<BenchmarkResult> => {\n const records = options.records ?? 100_000;\n const collection = options.collection ?? \"benchmark\";\n const batchSize = options.batchSize ?? 500;\n const startedAt = performance.now();\n\n for (let index = 0; index < records; index += batchSize) {\n const batch = Array.from({ length: Math.min(batchSize, records - index) }, (_, offset) =>\n options.storage.set(collection, createBenchmarkRecord(index + offset))\n );\n await Promise.all(batch);\n }\n\n return toResult(`${options.storage.name}:batch-writes`, records, startedAt);\n};\n\nexport const benchmarkAdapterFind = async (\n options: AdapterBenchmarkOptions\n): Promise<BenchmarkResult> => {\n const collection = options.collection ?? \"benchmark\";\n const startedAt = performance.now();\n const records = await options.storage.find(collection, {\n filters: { group: \"even\" },\n limit: 100,\n orderBy: \"createdAt\",\n sort: \"desc\"\n });\n\n return toResult(`${options.storage.name}:find`, records.length, startedAt);\n};\n\nexport const benchmarkIndexedFind = async (\n options: AdapterBenchmarkOptions\n): Promise<BenchmarkResult> => {\n const collection = options.collection ?? \"benchmark\";\n const storage = options.storage as IndexableStorageAdapter;\n\n if (typeof storage.createIndex === \"function\") {\n await storage.createIndex({\n collection,\n fields: [\"group\"],\n name: \"benchmark_group\"\n });\n }\n\n const startedAt = performance.now();\n const records = await options.storage.find(collection, {\n filters: { group: \"even\" },\n limit: 100\n });\n\n return toResult(`${options.storage.name}:indexed-find`, records.length, startedAt);\n};\n\n/** Seed + write/find suite sized for 100k-record adapter comparisons. */\nexport const runAdapterBenchmarkSuite = async (\n options: AdapterBenchmarkOptions\n): Promise<BenchmarkSuiteResult> => {\n const writes = await benchmarkAdapterWrites(options);\n const find = await benchmarkAdapterFind(options);\n const indexedFind = await benchmarkIndexedFind(options);\n\n return { find, indexedFind, writes };\n};\n\nexport const formatBenchmarkResult = (result: BenchmarkResult): string => {\n const throughput =\n result.throughputPerSecond === undefined\n ? \"\"\n : ` (${result.throughputPerSecond.toFixed(0)} ops/s)`;\n return `${result.name}: ${result.records} records in ${result.durationMs.toFixed(2)}ms${throughput}`;\n};\n\nconst toResult = (name: string, records: number, startedAt: number): BenchmarkResult => {\n const durationMs = performance.now() - startedAt;\n return {\n durationMs,\n name,\n records,\n ...(durationMs > 0 ? { throughputPerSecond: (records / durationMs) * 1000 } : {})\n };\n};\n"]}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@offlinejs/benchmarks",
3
+ "version": "0.1.0",
4
+ "description": "Benchmark utilities for OfflineJS adapters and sync flows.",
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ }
12
+ },
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "dependencies": {
17
+ "@offlinejs/types": "0.1.0"
18
+ },
19
+ "devDependencies": {
20
+ "tsup": "latest",
21
+ "typescript": "latest"
22
+ },
23
+ "publishConfig": {
24
+ "access": "public",
25
+ "registry": "https://registry.npmjs.org/"
26
+ },
27
+ "scripts": {
28
+ "build": "tsup",
29
+ "typecheck": "tsc --noEmit"
30
+ }
31
+ }