@adobe/data-persistence 0.9.90
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.
- package/LICENSE +21 -0
- package/README.md +258 -0
- package/dist/backend/memory-backend.d.ts +6 -0
- package/dist/backend/memory-backend.js +92 -0
- package/dist/backend/memory-backend.js.map +1 -0
- package/dist/backend/memory-backend.test.d.ts +1 -0
- package/dist/backend/memory-backend.test.js +7 -0
- package/dist/backend/memory-backend.test.js.map +1 -0
- package/dist/backend/memory-file.d.ts +7 -0
- package/dist/backend/memory-file.js +90 -0
- package/dist/backend/memory-file.js.map +1 -0
- package/dist/backend/memory-file.test.d.ts +1 -0
- package/dist/backend/memory-file.test.js +5 -0
- package/dist/backend/memory-file.test.js.map +1 -0
- package/dist/backend/persistence-backend.conformance.d.ts +10 -0
- package/dist/backend/persistence-backend.conformance.js +104 -0
- package/dist/backend/persistence-backend.conformance.js.map +1 -0
- package/dist/backend/persistence-backend.d.ts +54 -0
- package/dist/backend/persistence-backend.js +3 -0
- package/dist/backend/persistence-backend.js.map +1 -0
- package/dist/backend/random-access-file.conformance.d.ts +20 -0
- package/dist/backend/random-access-file.conformance.js +156 -0
- package/dist/backend/random-access-file.conformance.js.map +1 -0
- package/dist/backend/random-access-file.d.ts +39 -0
- package/dist/backend/random-access-file.js +3 -0
- package/dist/backend/random-access-file.js.map +1 -0
- package/dist/backend/validate-rel-path.d.ts +14 -0
- package/dist/backend/validate-rel-path.js +44 -0
- package/dist/backend/validate-rel-path.js.map +1 -0
- package/dist/backend/validate-rel-path.test.d.ts +1 -0
- package/dist/backend/validate-rel-path.test.js +37 -0
- package/dist/backend/validate-rel-path.test.js.map +1 -0
- package/dist/browser/browser-worker-bootstrap.d.ts +1 -0
- package/dist/browser/browser-worker-bootstrap.js +97 -0
- package/dist/browser/browser-worker-bootstrap.js.map +1 -0
- package/dist/browser/browser-worker-transport.browser.test.d.ts +1 -0
- package/dist/browser/browser-worker-transport.browser.test.js +156 -0
- package/dist/browser/browser-worker-transport.browser.test.js.map +1 -0
- package/dist/browser/browser-worker-transport.d.ts +33 -0
- package/dist/browser/browser-worker-transport.js +120 -0
- package/dist/browser/browser-worker-transport.js.map +1 -0
- package/dist/browser/create-opfs-provider.d.ts +23 -0
- package/dist/browser/create-opfs-provider.js +49 -0
- package/dist/browser/create-opfs-provider.js.map +1 -0
- package/dist/browser/index.d.ts +6 -0
- package/dist/browser/index.js +12 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/mount-opfs.d.ts +12 -0
- package/dist/browser/mount-opfs.js +15 -0
- package/dist/browser/mount-opfs.js.map +1 -0
- package/dist/browser/opfs-backend-lock.browser.test.d.ts +1 -0
- package/dist/browser/opfs-backend-lock.browser.test.js +127 -0
- package/dist/browser/opfs-backend-lock.browser.test.js.map +1 -0
- package/dist/browser/opfs-backend.d.ts +6 -0
- package/dist/browser/opfs-backend.js +162 -0
- package/dist/browser/opfs-backend.js.map +1 -0
- package/dist/browser/opfs-lock-test-worker.d.ts +1 -0
- package/dist/browser/opfs-lock-test-worker.js +50 -0
- package/dist/browser/opfs-lock-test-worker.js.map +1 -0
- package/dist/browser/opfs-sync-file.d.ts +10 -0
- package/dist/browser/opfs-sync-file.js +58 -0
- package/dist/browser/opfs-sync-file.js.map +1 -0
- package/dist/encoder/create-column-encoder.d.ts +15 -0
- package/dist/encoder/create-column-encoder.js +110 -0
- package/dist/encoder/create-column-encoder.js.map +1 -0
- package/dist/encoder/journal-snapshot-codec.d.ts +21 -0
- package/dist/encoder/journal-snapshot-codec.js +103 -0
- package/dist/encoder/journal-snapshot-codec.js.map +1 -0
- package/dist/encoder/journal-snapshot-codec.test.d.ts +1 -0
- package/dist/encoder/journal-snapshot-codec.test.js +96 -0
- package/dist/encoder/journal-snapshot-codec.test.js.map +1 -0
- package/dist/encoder/types.d.ts +72 -0
- package/dist/encoder/types.js +3 -0
- package/dist/encoder/types.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/journal/journal-codec.d.ts +28 -0
- package/dist/journal/journal-codec.js +82 -0
- package/dist/journal/journal-codec.js.map +1 -0
- package/dist/journal/journal-codec.test.d.ts +1 -0
- package/dist/journal/journal-codec.test.js +106 -0
- package/dist/journal/journal-codec.test.js.map +1 -0
- package/dist/journal/journal-entry.d.ts +63 -0
- package/dist/journal/journal-entry.js +28 -0
- package/dist/journal/journal-entry.js.map +1 -0
- package/dist/node/create-node-fs-provider.d.ts +34 -0
- package/dist/node/create-node-fs-provider.js +48 -0
- package/dist/node/create-node-fs-provider.js.map +1 -0
- package/dist/node/index.d.ts +6 -0
- package/dist/node/index.js +10 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/mount-node-fs.d.ts +12 -0
- package/dist/node/mount-node-fs.js +15 -0
- package/dist/node/mount-node-fs.js.map +1 -0
- package/dist/node/node-fs-backend-lock.node.test.d.ts +1 -0
- package/dist/node/node-fs-backend-lock.node.test.js +160 -0
- package/dist/node/node-fs-backend-lock.node.test.js.map +1 -0
- package/dist/node/node-fs-backend.d.ts +21 -0
- package/dist/node/node-fs-backend.js +186 -0
- package/dist/node/node-fs-backend.js.map +1 -0
- package/dist/node/node-fs-backend.node.test.d.ts +1 -0
- package/dist/node/node-fs-backend.node.test.js +17 -0
- package/dist/node/node-fs-backend.node.test.js.map +1 -0
- package/dist/node/node-fs-file.d.ts +6 -0
- package/dist/node/node-fs-file.js +57 -0
- package/dist/node/node-fs-file.js.map +1 -0
- package/dist/node/node-fs-file.node.test.d.ts +1 -0
- package/dist/node/node-fs-file.node.test.js +13 -0
- package/dist/node/node-fs-file.node.test.js.map +1 -0
- package/dist/node/node-fs-provider.node.test.d.ts +1 -0
- package/dist/node/node-fs-provider.node.test.js +119 -0
- package/dist/node/node-fs-provider.node.test.js.map +1 -0
- package/dist/node/node-worker-bootstrap.d.ts +1 -0
- package/dist/node/node-worker-bootstrap.js +104 -0
- package/dist/node/node-worker-bootstrap.js.map +1 -0
- package/dist/node/node-worker-transport.d.ts +27 -0
- package/dist/node/node-worker-transport.js +152 -0
- package/dist/node/node-worker-transport.js.map +1 -0
- package/dist/node/node-worker-transport.node.test.d.ts +1 -0
- package/dist/node/node-worker-transport.node.test.js +147 -0
- package/dist/node/node-worker-transport.node.test.js.map +1 -0
- package/dist/perftest/perf-harness.d.ts +74 -0
- package/dist/perftest/perf-harness.js +147 -0
- package/dist/perftest/perf-harness.js.map +1 -0
- package/dist/perftest/persistence-perf.d.ts +2 -0
- package/dist/perftest/persistence-perf.js +290 -0
- package/dist/perftest/persistence-perf.js.map +1 -0
- package/dist/perftest/run.d.ts +1 -0
- package/dist/perftest/run.js +28 -0
- package/dist/perftest/run.js.map +1 -0
- package/dist/provider/create-memory-provider.d.ts +16 -0
- package/dist/provider/create-memory-provider.js +44 -0
- package/dist/provider/create-memory-provider.js.map +1 -0
- package/dist/provider/mount.d.ts +20 -0
- package/dist/provider/mount.js +20 -0
- package/dist/provider/mount.js.map +1 -0
- package/dist/provider/persistence-provider.d.ts +63 -0
- package/dist/provider/persistence-provider.js +3 -0
- package/dist/provider/persistence-provider.js.map +1 -0
- package/dist/provider/persistence-provider.test.d.ts +9 -0
- package/dist/provider/persistence-provider.test.js +139 -0
- package/dist/provider/persistence-provider.test.js.map +1 -0
- package/dist/service/component-nonpersistent-durability.test.d.ts +1 -0
- package/dist/service/component-nonpersistent-durability.test.js +57 -0
- package/dist/service/component-nonpersistent-durability.test.js.map +1 -0
- package/dist/service/create-incremental-persistence-service.d.ts +7 -0
- package/dist/service/create-incremental-persistence-service.js +960 -0
- package/dist/service/create-incremental-persistence-service.js.map +1 -0
- package/dist/service/create-worker-persistence-service.d.ts +1 -0
- package/dist/service/create-worker-persistence-service.js +7 -0
- package/dist/service/create-worker-persistence-service.js.map +1 -0
- package/dist/service/create-worker-persistence-service.test.d.ts +1 -0
- package/dist/service/create-worker-persistence-service.test.js +291 -0
- package/dist/service/create-worker-persistence-service.test.js.map +1 -0
- package/dist/service/entity-location-cache.d.ts +15 -0
- package/dist/service/entity-location-cache.js +75 -0
- package/dist/service/entity-location-cache.js.map +1 -0
- package/dist/service/entity-location-density.test.d.ts +1 -0
- package/dist/service/entity-location-density.test.js +42 -0
- package/dist/service/entity-location-density.test.js.map +1 -0
- package/dist/service/incremental-persistence-service.d.ts +57 -0
- package/dist/service/incremental-persistence-service.js +3 -0
- package/dist/service/incremental-persistence-service.js.map +1 -0
- package/dist/service/intermediate-relocation-durability.test.d.ts +1 -0
- package/dist/service/intermediate-relocation-durability.test.js +89 -0
- package/dist/service/intermediate-relocation-durability.test.js.map +1 -0
- package/dist/service/internal-access.d.ts +34 -0
- package/dist/service/internal-access.js +43 -0
- package/dist/service/internal-access.js.map +1 -0
- package/dist/service/journal-replay.test.d.ts +1 -0
- package/dist/service/journal-replay.test.js +424 -0
- package/dist/service/journal-replay.test.js.map +1 -0
- package/dist/service/journal-storage-durability.test.d.ts +1 -0
- package/dist/service/journal-storage-durability.test.js +171 -0
- package/dist/service/journal-storage-durability.test.js.map +1 -0
- package/dist/service/load-roundtrip.test.d.ts +1 -0
- package/dist/service/load-roundtrip.test.js +224 -0
- package/dist/service/load-roundtrip.test.js.map +1 -0
- package/dist/service/persistence-complexity.test.d.ts +1 -0
- package/dist/service/persistence-complexity.test.js +275 -0
- package/dist/service/persistence-complexity.test.js.map +1 -0
- package/dist/service/worker-persistence-service.d.ts +24 -0
- package/dist/service/worker-persistence-service.js +8 -0
- package/dist/service/worker-persistence-service.js.map +1 -0
- package/dist/transport/inprocess-transport.d.ts +15 -0
- package/dist/transport/inprocess-transport.js +64 -0
- package/dist/transport/inprocess-transport.js.map +1 -0
- package/dist/transport/inprocess-transport.test.d.ts +1 -0
- package/dist/transport/inprocess-transport.test.js +100 -0
- package/dist/transport/inprocess-transport.test.js.map +1 -0
- package/dist/transport/router.d.ts +12 -0
- package/dist/transport/router.js +146 -0
- package/dist/transport/router.js.map +1 -0
- package/dist/transport/transport.d.ts +105 -0
- package/dist/transport/transport.js +3 -0
- package/dist/transport/transport.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal async-aware performance harness for the persistence layer.
|
|
3
|
+
*
|
|
4
|
+
* Differs from `packages/data/src/perftest/perf-test.ts` in two ways:
|
|
5
|
+
*
|
|
6
|
+
* 1. `run` is `async` because every persistence operation drains
|
|
7
|
+
* through a transport whose acks resolve on a microtask. A
|
|
8
|
+
* sync-only harness would either record zero (work hasn't
|
|
9
|
+
* finished) or include only the synchronous `send()` push,
|
|
10
|
+
* which would be misleading.
|
|
11
|
+
*
|
|
12
|
+
* 2. There's a `setupBatch` hook called once per measurement loop
|
|
13
|
+
* iteration. Some scenarios (e.g. "steady delete") consume an
|
|
14
|
+
* entity per iteration; this lets the scenario refill its
|
|
15
|
+
* working set without that cost being attributed to `run()`.
|
|
16
|
+
*
|
|
17
|
+
* The harness is intentionally tiny — it owns warmup, auto-tuning,
|
|
18
|
+
* the measurement window, and printing. Scenarios own everything
|
|
19
|
+
* else (database, transport, backend, scoring).
|
|
20
|
+
*/
|
|
21
|
+
export interface PerfScenario {
|
|
22
|
+
/**
|
|
23
|
+
* Friendly name shown in the results table.
|
|
24
|
+
*/
|
|
25
|
+
readonly name: string;
|
|
26
|
+
/**
|
|
27
|
+
* One-time setup (database creation, populating N entities, etc).
|
|
28
|
+
* Called once per `n` choice during auto-tune; the measurement
|
|
29
|
+
* window itself reuses the resulting state.
|
|
30
|
+
*/
|
|
31
|
+
setup(n: number): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Optional per-iteration setup. Returns a cost-free reference
|
|
34
|
+
* (entity ids, indices, etc) that `run()` can use without
|
|
35
|
+
* computing it during measurement. Called once per `run()` call.
|
|
36
|
+
*/
|
|
37
|
+
setupBatch?(): Promise<unknown>;
|
|
38
|
+
/**
|
|
39
|
+
* The measured operation. Must perform exactly ONE logical
|
|
40
|
+
* persistence operation (one transaction, one checkpoint, one
|
|
41
|
+
* load — whatever the scenario says it measures). Returns when
|
|
42
|
+
* the operation has fully drained on the persistence side.
|
|
43
|
+
*/
|
|
44
|
+
run(batch: unknown): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Tear down the database, dispose the service, close the
|
|
47
|
+
* transport. Called once per scenario.
|
|
48
|
+
*/
|
|
49
|
+
cleanup(): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Auto-tune seed. Scenarios with high per-op cost should set
|
|
52
|
+
* this lower than the default (1000) so the first probe doesn't
|
|
53
|
+
* waste the budget.
|
|
54
|
+
*/
|
|
55
|
+
readonly startN?: number;
|
|
56
|
+
}
|
|
57
|
+
export interface PerfResult {
|
|
58
|
+
readonly name: string;
|
|
59
|
+
readonly n: number;
|
|
60
|
+
readonly samples: number;
|
|
61
|
+
readonly meanUs: number;
|
|
62
|
+
readonly minUs: number;
|
|
63
|
+
readonly p50Us: number;
|
|
64
|
+
readonly p99Us: number;
|
|
65
|
+
readonly opsPerSec: number;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Run a single scenario through the warmup + measurement pipeline.
|
|
69
|
+
*/
|
|
70
|
+
export declare const runScenario: (scenario: PerfScenario) => Promise<PerfResult>;
|
|
71
|
+
/**
|
|
72
|
+
* Run all scenarios sequentially and print a results table.
|
|
73
|
+
*/
|
|
74
|
+
export declare const runAll: (scenarios: readonly PerfScenario[]) => Promise<readonly PerfResult[]>;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
const DEFAULT_START_N = 1000;
|
|
3
|
+
// Target per-iteration time: 0.5–150 ms. Below 0.5 ms timing
|
|
4
|
+
// resolution dominates; above 150 ms we get too few samples in the
|
|
5
|
+
// 1-second budget for stable percentiles. The wide upper bound is
|
|
6
|
+
// deliberate — scenarios whose cold probe drifts to ~70 ms because
|
|
7
|
+
// of GC noise should NOT trigger auto-tune to halve N, because the
|
|
8
|
+
// halved version is then evaluated under DIFFERENT per-tx overhead
|
|
9
|
+
// proportions and produces non-comparable numbers across runs.
|
|
10
|
+
const TARGET_MIN_MS = 0.5;
|
|
11
|
+
const TARGET_MAX_MS = 150;
|
|
12
|
+
const MIN_AUTO_N = 1;
|
|
13
|
+
const MAX_AUTO_N = 100_000;
|
|
14
|
+
const WARMUP_MS = 100;
|
|
15
|
+
const MEASURE_BUDGET_MS = 1000;
|
|
16
|
+
const now = () => performance.now();
|
|
17
|
+
const percentile = (sortedAsc, p) => {
|
|
18
|
+
if (sortedAsc.length === 0)
|
|
19
|
+
return 0;
|
|
20
|
+
const idx = Math.min(sortedAsc.length - 1, Math.floor((p / 100) * sortedAsc.length));
|
|
21
|
+
return sortedAsc[idx];
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Auto-tune `n` so a single `run()` lands in TARGET_MIN_MS..TARGET_MAX_MS.
|
|
25
|
+
* Returns the chosen n and (re-)leaves the scenario set up at that n.
|
|
26
|
+
*/
|
|
27
|
+
const tuneN = async (scenario) => {
|
|
28
|
+
let n = scenario.startN ?? DEFAULT_START_N;
|
|
29
|
+
for (let attempt = 0; attempt < 4; attempt++) {
|
|
30
|
+
await scenario.cleanup().catch(() => undefined);
|
|
31
|
+
await scenario.setup(n);
|
|
32
|
+
const batch = scenario.setupBatch ? await scenario.setupBatch() : undefined;
|
|
33
|
+
const start = now();
|
|
34
|
+
await scenario.run(batch);
|
|
35
|
+
const elapsed = Math.max(now() - start, 0.001);
|
|
36
|
+
if (elapsed >= TARGET_MIN_MS && elapsed <= TARGET_MAX_MS)
|
|
37
|
+
return n;
|
|
38
|
+
const target = (TARGET_MIN_MS + TARGET_MAX_MS) / 2;
|
|
39
|
+
const ratio = target / elapsed;
|
|
40
|
+
const next = Math.max(MIN_AUTO_N, Math.min(MAX_AUTO_N, Math.round(n * ratio)));
|
|
41
|
+
if (next === n)
|
|
42
|
+
return n;
|
|
43
|
+
n = next;
|
|
44
|
+
}
|
|
45
|
+
return n;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Run a single scenario through the warmup + measurement pipeline.
|
|
49
|
+
*/
|
|
50
|
+
export const runScenario = async (scenario) => {
|
|
51
|
+
const n = await tuneN(scenario);
|
|
52
|
+
// Warmup: keep calling run() (re-batching as needed) for ~100ms so
|
|
53
|
+
// V8 fully optimizes hot functions before any sample is recorded.
|
|
54
|
+
const warmupEnd = now() + WARMUP_MS;
|
|
55
|
+
while (now() < warmupEnd) {
|
|
56
|
+
const batch = scenario.setupBatch ? await scenario.setupBatch() : undefined;
|
|
57
|
+
await scenario.run(batch);
|
|
58
|
+
}
|
|
59
|
+
// Measurement window. We sample as many runs as fit into the
|
|
60
|
+
// budget. Each sample is ms-per-run-of-N-ops; we convert to
|
|
61
|
+
// μs-per-op by dividing by n at report time.
|
|
62
|
+
const samplesMs = [];
|
|
63
|
+
const budgetEnd = now() + MEASURE_BUDGET_MS;
|
|
64
|
+
while (now() < budgetEnd) {
|
|
65
|
+
const batch = scenario.setupBatch ? await scenario.setupBatch() : undefined;
|
|
66
|
+
const start = now();
|
|
67
|
+
await scenario.run(batch);
|
|
68
|
+
const elapsed = now() - start;
|
|
69
|
+
samplesMs.push(elapsed);
|
|
70
|
+
}
|
|
71
|
+
await scenario.cleanup().catch(() => undefined);
|
|
72
|
+
if (samplesMs.length === 0) {
|
|
73
|
+
// Pathological: even a single run blew the budget. Report
|
|
74
|
+
// a single sample so callers can still see SOMETHING.
|
|
75
|
+
return {
|
|
76
|
+
name: scenario.name,
|
|
77
|
+
n,
|
|
78
|
+
samples: 0,
|
|
79
|
+
meanUs: NaN,
|
|
80
|
+
minUs: NaN,
|
|
81
|
+
p50Us: NaN,
|
|
82
|
+
p99Us: NaN,
|
|
83
|
+
opsPerSec: NaN,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
const samplesUs = samplesMs.map(ms => (ms * 1000) / n);
|
|
87
|
+
const sorted = [...samplesUs].sort((a, b) => a - b);
|
|
88
|
+
const mean = samplesUs.reduce((a, b) => a + b, 0) / samplesUs.length;
|
|
89
|
+
const min = sorted[0];
|
|
90
|
+
const p50 = percentile(sorted, 50);
|
|
91
|
+
const p99 = percentile(sorted, 99);
|
|
92
|
+
const opsPerSec = mean > 0 ? 1_000_000 / mean : Infinity;
|
|
93
|
+
return {
|
|
94
|
+
name: scenario.name,
|
|
95
|
+
n,
|
|
96
|
+
samples: samplesMs.length,
|
|
97
|
+
meanUs: mean,
|
|
98
|
+
minUs: min,
|
|
99
|
+
p50Us: p50,
|
|
100
|
+
p99Us: p99,
|
|
101
|
+
opsPerSec,
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* Run all scenarios sequentially and print a results table.
|
|
106
|
+
*/
|
|
107
|
+
export const runAll = async (scenarios) => {
|
|
108
|
+
const results = [];
|
|
109
|
+
for (const scenario of scenarios) {
|
|
110
|
+
process.stdout.write(` ${scenario.name} ... `);
|
|
111
|
+
const start = now();
|
|
112
|
+
try {
|
|
113
|
+
const result = await runScenario(scenario);
|
|
114
|
+
results.push(result);
|
|
115
|
+
const wall = ((now() - start) / 1000).toFixed(1);
|
|
116
|
+
process.stdout.write(`${result.meanUs.toFixed(2)} μs/op (${result.samples} samples, ${wall}s wall)\n`);
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
process.stdout.write(`FAILED: ${err.message}\n`);
|
|
120
|
+
throw err;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
printTable(results);
|
|
124
|
+
return results;
|
|
125
|
+
};
|
|
126
|
+
const printTable = (results) => {
|
|
127
|
+
if (results.length === 0)
|
|
128
|
+
return;
|
|
129
|
+
const rows = results.map(r => ({
|
|
130
|
+
scenario: r.name,
|
|
131
|
+
N: r.n,
|
|
132
|
+
samples: r.samples,
|
|
133
|
+
"μs/op (mean)": r.meanUs.toFixed(2),
|
|
134
|
+
"μs/op (min)": r.minUs.toFixed(2),
|
|
135
|
+
"μs/op (p50)": r.p50Us.toFixed(2),
|
|
136
|
+
"μs/op (p99)": r.p99Us.toFixed(2),
|
|
137
|
+
"ops/sec": Math.round(r.opsPerSec).toLocaleString(),
|
|
138
|
+
}));
|
|
139
|
+
if (typeof console.table === "function") {
|
|
140
|
+
console.table(rows);
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
for (const row of rows)
|
|
144
|
+
console.log(row);
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
//# sourceMappingURL=perf-harness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"perf-harness.js","sourceRoot":"","sources":["../../src/perftest/perf-harness.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
import { Database } from "@adobe/data/ecs";
|
|
3
|
+
import { F32, Vec3 } from "@adobe/data/math";
|
|
4
|
+
import { createMemoryBackend } from "../backend/memory-backend.js";
|
|
5
|
+
import { createWorkerPersistenceService } from "../service/create-worker-persistence-service.js";
|
|
6
|
+
// All scenarios share this database shape so wall-time numbers
|
|
7
|
+
// are directly comparable across scenarios. Three components, one
|
|
8
|
+
// archetype — small enough that per-tx work is dominated by the
|
|
9
|
+
// persistence layer itself, not the schema's encoder cost.
|
|
10
|
+
const createTestDb = () => {
|
|
11
|
+
const plugin = Database.Plugin.create({
|
|
12
|
+
components: {
|
|
13
|
+
position: Vec3.schema,
|
|
14
|
+
velocity: Vec3.schema,
|
|
15
|
+
mass: F32.schema,
|
|
16
|
+
},
|
|
17
|
+
archetypes: {
|
|
18
|
+
Particle: ["position", "velocity", "mass"],
|
|
19
|
+
},
|
|
20
|
+
transactions: {
|
|
21
|
+
spawn(t, args) {
|
|
22
|
+
return t.archetypes.Particle.insert({
|
|
23
|
+
position: [args.x, args.y, args.z],
|
|
24
|
+
velocity: [0, 0, 0],
|
|
25
|
+
mass: args.mass,
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
move(t, args) {
|
|
29
|
+
t.update(args.entity, { position: [args.x, args.y, args.z] });
|
|
30
|
+
},
|
|
31
|
+
updateAll(t, args) {
|
|
32
|
+
t.update(args.entity, {
|
|
33
|
+
position: [args.x, args.y, args.z],
|
|
34
|
+
velocity: [args.vx, args.vy, args.vz],
|
|
35
|
+
mass: args.mass,
|
|
36
|
+
});
|
|
37
|
+
},
|
|
38
|
+
kill(t, entity) {
|
|
39
|
+
t.delete(entity);
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
return Database.create(plugin);
|
|
44
|
+
};
|
|
45
|
+
const setupPopulated = async (n) => {
|
|
46
|
+
const db = createTestDb();
|
|
47
|
+
const backend = createMemoryBackend();
|
|
48
|
+
const service = await createWorkerPersistenceService({
|
|
49
|
+
database: db,
|
|
50
|
+
backend,
|
|
51
|
+
// Disable both checkpoint paths so they never fire during a
|
|
52
|
+
// measurement window and skew numbers. Each scenario that
|
|
53
|
+
// wants to measure checkpoint cost calls it explicitly.
|
|
54
|
+
checkpoint: { everyNTransactions: 0, idleMs: 0 },
|
|
55
|
+
});
|
|
56
|
+
const ids = [];
|
|
57
|
+
for (let i = 0; i < n; i++) {
|
|
58
|
+
const id = db.transactions.spawn({ x: i, y: i, z: i, mass: 1 });
|
|
59
|
+
ids.push(id);
|
|
60
|
+
}
|
|
61
|
+
await service.flush();
|
|
62
|
+
return { db, service, ids };
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Steady-state per-tx update touching ONE component on ONE entity.
|
|
66
|
+
*
|
|
67
|
+
* This is the dominant case in real workloads: gameplay tick that
|
|
68
|
+
* moves a few entities per frame. The per-component-write
|
|
69
|
+
* optimization (architectural review #4) targets this case
|
|
70
|
+
* specifically — its win shows up here as a 3× drop vs writing all
|
|
71
|
+
* three columns per tx.
|
|
72
|
+
*/
|
|
73
|
+
const moveOneComponent = () => {
|
|
74
|
+
let state = null;
|
|
75
|
+
let cursor = 0;
|
|
76
|
+
return {
|
|
77
|
+
name: "tx: update 1 component on 1 entity (steady)",
|
|
78
|
+
startN: 200,
|
|
79
|
+
async setup(n) {
|
|
80
|
+
state = await setupPopulated(1000);
|
|
81
|
+
cursor = 0;
|
|
82
|
+
void n; // n here is iterations per measurement, not world size
|
|
83
|
+
},
|
|
84
|
+
async run() {
|
|
85
|
+
const s = state;
|
|
86
|
+
for (let i = 0; i < 200; i++) {
|
|
87
|
+
const e = s.ids[cursor];
|
|
88
|
+
cursor = (cursor + 1) % s.ids.length;
|
|
89
|
+
s.db.transactions.move({ entity: e, x: i, y: i, z: i });
|
|
90
|
+
}
|
|
91
|
+
await s.service.flush();
|
|
92
|
+
},
|
|
93
|
+
async cleanup() {
|
|
94
|
+
await state?.service.dispose();
|
|
95
|
+
state = null;
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
const moveAllComponents = () => {
|
|
100
|
+
let state = null;
|
|
101
|
+
let cursor = 0;
|
|
102
|
+
return {
|
|
103
|
+
name: "tx: update 3 components on 1 entity",
|
|
104
|
+
startN: 200,
|
|
105
|
+
async setup() {
|
|
106
|
+
state = await setupPopulated(1000);
|
|
107
|
+
cursor = 0;
|
|
108
|
+
},
|
|
109
|
+
async run() {
|
|
110
|
+
const s = state;
|
|
111
|
+
for (let i = 0; i < 200; i++) {
|
|
112
|
+
const e = s.ids[cursor];
|
|
113
|
+
cursor = (cursor + 1) % s.ids.length;
|
|
114
|
+
s.db.transactions.updateAll({
|
|
115
|
+
entity: e,
|
|
116
|
+
x: i, y: i, z: i,
|
|
117
|
+
vx: -i, vy: -i, vz: -i,
|
|
118
|
+
mass: i + 1,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
await s.service.flush();
|
|
122
|
+
},
|
|
123
|
+
async cleanup() {
|
|
124
|
+
await state?.service.dispose();
|
|
125
|
+
state = null;
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
const insertSteady = () => {
|
|
130
|
+
let state = null;
|
|
131
|
+
return {
|
|
132
|
+
name: "tx: insert (3 columns)",
|
|
133
|
+
startN: 200,
|
|
134
|
+
async setup() {
|
|
135
|
+
state = await setupPopulated(1000);
|
|
136
|
+
},
|
|
137
|
+
async run() {
|
|
138
|
+
const s = state;
|
|
139
|
+
for (let i = 0; i < 200; i++) {
|
|
140
|
+
s.db.transactions.spawn({ x: i, y: i, z: i, mass: 1 });
|
|
141
|
+
}
|
|
142
|
+
await s.service.flush();
|
|
143
|
+
},
|
|
144
|
+
async cleanup() {
|
|
145
|
+
await state?.service.dispose();
|
|
146
|
+
state = null;
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
};
|
|
150
|
+
/**
|
|
151
|
+
* Steady-state delete with the swap-remove side effect: the
|
|
152
|
+
* persistence service detects the moved entity and emits a synthetic
|
|
153
|
+
* full-row update for it. This scenario refills the working set in
|
|
154
|
+
* setupBatch so the iteration count is pinned.
|
|
155
|
+
*/
|
|
156
|
+
const deleteWithSwap = () => {
|
|
157
|
+
let state = null;
|
|
158
|
+
let killCount = 0;
|
|
159
|
+
return {
|
|
160
|
+
name: "tx: delete + swap-remove side effect",
|
|
161
|
+
startN: 100,
|
|
162
|
+
async setup() {
|
|
163
|
+
state = await setupPopulated(2000);
|
|
164
|
+
killCount = 0;
|
|
165
|
+
},
|
|
166
|
+
async setupBatch() {
|
|
167
|
+
// Refill the working set so each measurement iteration
|
|
168
|
+
// has a known number of victims to kill. Done OUTSIDE
|
|
169
|
+
// run() so its cost isn't attributed to delete.
|
|
170
|
+
const s = state;
|
|
171
|
+
while (s.ids.length < 1000) {
|
|
172
|
+
const id = s.db.transactions.spawn({ x: 0, y: 0, z: 0, mass: 1 });
|
|
173
|
+
s.ids.push(id);
|
|
174
|
+
}
|
|
175
|
+
await s.service.flush();
|
|
176
|
+
},
|
|
177
|
+
async run() {
|
|
178
|
+
const s = state;
|
|
179
|
+
for (let i = 0; i < 100; i++) {
|
|
180
|
+
// Always delete from the middle so swap-remove
|
|
181
|
+
// actually triggers (deleting the LAST row would not).
|
|
182
|
+
const idx = Math.floor(s.ids.length / 2);
|
|
183
|
+
const e = s.ids[idx];
|
|
184
|
+
s.ids.splice(idx, 1);
|
|
185
|
+
s.db.transactions.kill(e);
|
|
186
|
+
killCount += 1;
|
|
187
|
+
}
|
|
188
|
+
await s.service.flush();
|
|
189
|
+
},
|
|
190
|
+
async cleanup() {
|
|
191
|
+
void killCount;
|
|
192
|
+
await state?.service.dispose();
|
|
193
|
+
state = null;
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
};
|
|
197
|
+
const checkpointAfterUpdates = () => {
|
|
198
|
+
let state = null;
|
|
199
|
+
let cursor = 0;
|
|
200
|
+
return {
|
|
201
|
+
name: "checkpoint: after 1k updates",
|
|
202
|
+
startN: 1,
|
|
203
|
+
async setup() {
|
|
204
|
+
state = await setupPopulated(1000);
|
|
205
|
+
cursor = 0;
|
|
206
|
+
},
|
|
207
|
+
async setupBatch() {
|
|
208
|
+
// Dirty 1k rows since the last checkpoint so the
|
|
209
|
+
// checkpoint actually has work to do (write a full
|
|
210
|
+
// manifest, then truncate the journal).
|
|
211
|
+
const s = state;
|
|
212
|
+
for (let i = 0; i < 1000; i++) {
|
|
213
|
+
const e = s.ids[cursor];
|
|
214
|
+
cursor = (cursor + 1) % s.ids.length;
|
|
215
|
+
s.db.transactions.move({ entity: e, x: i, y: i, z: i });
|
|
216
|
+
}
|
|
217
|
+
await s.service.flush();
|
|
218
|
+
},
|
|
219
|
+
async run() {
|
|
220
|
+
await state.service.checkpoint();
|
|
221
|
+
},
|
|
222
|
+
async cleanup() {
|
|
223
|
+
await state?.service.dispose();
|
|
224
|
+
state = null;
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
};
|
|
228
|
+
/**
|
|
229
|
+
* Cold-start load(): populate, checkpoint, dispose, then create a
|
|
230
|
+
* fresh service with a fresh database against the SAME backend and
|
|
231
|
+
* measure load() time. This is the single-shot recovery path users
|
|
232
|
+
* see at app startup.
|
|
233
|
+
*/
|
|
234
|
+
const loadCold = () => {
|
|
235
|
+
let backend = null;
|
|
236
|
+
let svc = null;
|
|
237
|
+
let db = null;
|
|
238
|
+
return {
|
|
239
|
+
name: "load: 1k entities, single-shot",
|
|
240
|
+
startN: 1,
|
|
241
|
+
async setup() {
|
|
242
|
+
// One-time prep: build a fully-checkpointed snapshot in
|
|
243
|
+
// the backend that we'll re-load each iteration.
|
|
244
|
+
const seedDb = createTestDb();
|
|
245
|
+
backend = createMemoryBackend();
|
|
246
|
+
const seedSvc = await createWorkerPersistenceService({
|
|
247
|
+
database: seedDb,
|
|
248
|
+
backend,
|
|
249
|
+
checkpoint: { everyNTransactions: 0, idleMs: 0 },
|
|
250
|
+
});
|
|
251
|
+
for (let i = 0; i < 1000; i++) {
|
|
252
|
+
seedDb.transactions.spawn({ x: i, y: i, z: i, mass: 1 });
|
|
253
|
+
}
|
|
254
|
+
await seedSvc.flush();
|
|
255
|
+
await seedSvc.checkpoint();
|
|
256
|
+
await seedSvc.dispose();
|
|
257
|
+
},
|
|
258
|
+
async setupBatch() {
|
|
259
|
+
// A fresh database + service per iteration — load() is a
|
|
260
|
+
// one-shot operation and reusing the same service would
|
|
261
|
+
// make replay no-op after the first iteration.
|
|
262
|
+
if (svc !== null)
|
|
263
|
+
await svc.dispose();
|
|
264
|
+
db = createTestDb();
|
|
265
|
+
svc = await createWorkerPersistenceService({
|
|
266
|
+
database: db,
|
|
267
|
+
backend: backend,
|
|
268
|
+
checkpoint: { everyNTransactions: 0, idleMs: 0 },
|
|
269
|
+
});
|
|
270
|
+
},
|
|
271
|
+
async run() {
|
|
272
|
+
await svc.load();
|
|
273
|
+
},
|
|
274
|
+
async cleanup() {
|
|
275
|
+
await svc?.dispose();
|
|
276
|
+
svc = null;
|
|
277
|
+
db = null;
|
|
278
|
+
backend = null;
|
|
279
|
+
},
|
|
280
|
+
};
|
|
281
|
+
};
|
|
282
|
+
export const persistenceScenarios = [
|
|
283
|
+
moveOneComponent(),
|
|
284
|
+
moveAllComponents(),
|
|
285
|
+
insertSteady(),
|
|
286
|
+
deleteWithSwap(),
|
|
287
|
+
checkpointAfterUpdates(),
|
|
288
|
+
loadCold(),
|
|
289
|
+
];
|
|
290
|
+
//# sourceMappingURL=persistence-perf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistence-perf.js","sourceRoot":"","sources":["../../src/perftest/persistence-perf.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
import { runAll } from "./perf-harness.js";
|
|
3
|
+
import { persistenceScenarios } from "./persistence-perf.js";
|
|
4
|
+
/**
|
|
5
|
+
* Persistence perftest entry point.
|
|
6
|
+
*
|
|
7
|
+
* Run with:
|
|
8
|
+
*
|
|
9
|
+
* pnpm --filter @adobe/data-persistence run perf
|
|
10
|
+
*
|
|
11
|
+
* The runner uses the in-process transport so wall-time numbers
|
|
12
|
+
* exclude postMessage overhead and isolate the persistence
|
|
13
|
+
* service's own per-tx cost. Worker-thread / web-worker numbers
|
|
14
|
+
* will add 1–10 μs of postMessage round-trip per op on top of
|
|
15
|
+
* what's reported here.
|
|
16
|
+
*/
|
|
17
|
+
const main = async () => {
|
|
18
|
+
console.log("@adobe/data-persistence perftest");
|
|
19
|
+
console.log("================================");
|
|
20
|
+
console.log("(in-process transport; reported numbers exclude postMessage overhead)");
|
|
21
|
+
console.log("");
|
|
22
|
+
await runAll(persistenceScenarios);
|
|
23
|
+
};
|
|
24
|
+
main().catch((err) => {
|
|
25
|
+
console.error(err);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
});
|
|
28
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/perftest/run.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAEvD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D;;;;;;;;;;;;GAYG;AACH,MAAM,IAAI,GAAG,KAAK,IAAmB,EAAE;IACnC,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,uEAAuE,CAAC,CAAC;IACrF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;AACvC,CAAC,CAAC;AAEF,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC1B,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { PersistenceProvider } from "./persistence-provider.js";
|
|
2
|
+
/**
|
|
3
|
+
* Creates an in-memory persistence provider. All data is lost when the
|
|
4
|
+
* mount is disposed.
|
|
5
|
+
*
|
|
6
|
+
* Primarily useful for tests and for prototyping without configuring a
|
|
7
|
+
* real storage backend.
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { mount } from "@adobe/data-persistence";
|
|
11
|
+
* import { createMemoryProvider } from "@adobe/data-persistence";
|
|
12
|
+
*
|
|
13
|
+
* const m = await mount(createMemoryProvider(), database);
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare const createMemoryProvider: () => PersistenceProvider;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
import { createMemoryBackend } from "../backend/memory-backend.js";
|
|
3
|
+
import { createInprocessTransport } from "../transport/inprocess-transport.js";
|
|
4
|
+
import { createIncrementalPersistenceService } from "../service/create-incremental-persistence-service.js";
|
|
5
|
+
/**
|
|
6
|
+
* Creates an in-memory persistence provider. All data is lost when the
|
|
7
|
+
* mount is disposed.
|
|
8
|
+
*
|
|
9
|
+
* Primarily useful for tests and for prototyping without configuring a
|
|
10
|
+
* real storage backend.
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { mount } from "@adobe/data-persistence";
|
|
14
|
+
* import { createMemoryProvider } from "@adobe/data-persistence";
|
|
15
|
+
*
|
|
16
|
+
* const m = await mount(createMemoryProvider(), database);
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export const createMemoryProvider = () => {
|
|
20
|
+
// A single backend shared across all mounts from this provider instance,
|
|
21
|
+
// so that a second mount can load data written by a previous mount.
|
|
22
|
+
const backend = createMemoryBackend();
|
|
23
|
+
return {
|
|
24
|
+
providerName: "MemoryProvider",
|
|
25
|
+
async mount(database, mountOptions) {
|
|
26
|
+
const transport = createInprocessTransport(backend);
|
|
27
|
+
const service = await createIncrementalPersistenceService({
|
|
28
|
+
database,
|
|
29
|
+
backend,
|
|
30
|
+
transport,
|
|
31
|
+
autoPersist: mountOptions?.autoPersist,
|
|
32
|
+
checkpoint: mountOptions?.checkpoint,
|
|
33
|
+
});
|
|
34
|
+
return {
|
|
35
|
+
service,
|
|
36
|
+
async dispose() {
|
|
37
|
+
await service.dispose();
|
|
38
|
+
await transport.close();
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=create-memory-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-memory-provider.js","sourceRoot":"","sources":["../../src/provider/create-memory-provider.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAGvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,OAAO,EAAE,mCAAmC,EAAE,MAAM,sDAAsD,CAAC;AAG3G;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAwB,EAAE;IAC1D,yEAAyE;IACzE,oEAAoE;IACpE,MAAM,OAAO,GAAG,mBAAmB,EAAE,CAAC;IAEtC,OAAO;QACP,YAAY,EAAE,gBAAgB;QAE9B,KAAK,CAAC,KAAK,CACP,QAA0D,EAC1D,YAAmC;YAEnC,MAAM,SAAS,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;YACpD,MAAM,OAAO,GAAG,MAAM,mCAAmC,CAAC;gBACtD,QAAQ;gBACR,OAAO;gBACP,SAAS;gBACT,WAAW,EAAE,YAAY,EAAE,WAAW;gBACtC,UAAU,EAAE,YAAY,EAAE,UAAU;aACvC,CAAC,CAAC;YAEH,OAAO;gBACH,OAAO;gBACP,KAAK,CAAC,OAAO;oBACT,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;oBACxB,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;gBAC5B,CAAC;aACJ,CAAC;QACN,CAAC;KACA,CAAC;AACN,CAAC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Database } from "@adobe/data/ecs";
|
|
2
|
+
import type { PersistenceMount, PersistenceProvider, ProviderMountOptions } from "./persistence-provider.js";
|
|
3
|
+
/**
|
|
4
|
+
* Mount a persistence session using the supplied provider.
|
|
5
|
+
*
|
|
6
|
+
* This is the single entry point for all persistence. The provider
|
|
7
|
+
* encapsulates the storage strategy — Node.js `fs`, OPFS, in-memory, or
|
|
8
|
+
* a custom cloud implementation.
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { mount } from "@adobe/data-persistence";
|
|
12
|
+
* import { createNodeFsProvider } from "@adobe/data-persistence/node";
|
|
13
|
+
*
|
|
14
|
+
* const m = await mount(createNodeFsProvider("/tmp/my-db"), database);
|
|
15
|
+
* await m.service.load();
|
|
16
|
+
* // ...run app...
|
|
17
|
+
* await m.dispose();
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare const mount: (provider: PersistenceProvider, database: Database<any, any, any, any, any, any, any, any>, options?: ProviderMountOptions) => Promise<PersistenceMount>;
|