dataply 0.0.17 → 0.0.18-alpha.1
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/dist/cjs/index.js +71 -63
- package/dist/types/core/RowTableEngine.d.ts +5 -4
- package/package.json +2 -2
- package/readme.md +7 -7
package/dist/cjs/index.js
CHANGED
|
@@ -1857,7 +1857,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
1857
1857
|
return node;
|
|
1858
1858
|
}
|
|
1859
1859
|
_updateNode(node) {
|
|
1860
|
-
this.mvcc.write(node.id,
|
|
1860
|
+
this.mvcc.write(node.id, node);
|
|
1861
1861
|
this.nodes.set(node.id, node);
|
|
1862
1862
|
}
|
|
1863
1863
|
_deleteNode(node) {
|
|
@@ -2686,7 +2686,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
2686
2686
|
return node;
|
|
2687
2687
|
}
|
|
2688
2688
|
async _updateNode(node) {
|
|
2689
|
-
await this.mvcc.write(node.id,
|
|
2689
|
+
await this.mvcc.write(node.id, node);
|
|
2690
2690
|
this.nodes.set(node.id, node);
|
|
2691
2691
|
}
|
|
2692
2692
|
async _deleteNode(node) {
|
|
@@ -8359,75 +8359,84 @@ var RowTableEngine = class {
|
|
|
8359
8359
|
};
|
|
8360
8360
|
}
|
|
8361
8361
|
/**
|
|
8362
|
-
* Inserts data.
|
|
8363
|
-
* @param data
|
|
8362
|
+
* Inserts data (batch insert).
|
|
8363
|
+
* @param dataList Array of data to insert
|
|
8364
8364
|
* @param incrementRowCount Whether to increment the row count to metadata
|
|
8365
|
+
* @param overflowForcly Force overflow page creation for all data
|
|
8365
8366
|
* @param tx Transaction
|
|
8366
|
-
* @returns
|
|
8367
|
+
* @returns Array of PKs of the inserted data
|
|
8367
8368
|
*/
|
|
8368
|
-
async insert(
|
|
8369
|
+
async insert(dataList, incrementRowCount, overflowForcly, tx) {
|
|
8370
|
+
if (dataList.length === 0) {
|
|
8371
|
+
return [];
|
|
8372
|
+
}
|
|
8369
8373
|
await tx.__acquireWriteLock(0);
|
|
8374
|
+
const btx = await this.getBPTreeTransaction(tx);
|
|
8375
|
+
const pks = [];
|
|
8370
8376
|
const metadataPage = await this.pfs.getMetadata(tx);
|
|
8371
|
-
|
|
8377
|
+
let lastPk = this.metadataPageManager.getLastRowPk(metadataPage);
|
|
8372
8378
|
let lastInsertDataPageId = this.metadataPageManager.getLastInsertPageId(metadataPage);
|
|
8373
8379
|
let lastInsertDataPage = await this.pfs.get(lastInsertDataPageId, tx);
|
|
8374
8380
|
if (!this.factory.isDataPage(lastInsertDataPage)) {
|
|
8375
8381
|
throw new Error(`Last insert page is not data page`);
|
|
8376
8382
|
}
|
|
8377
|
-
const
|
|
8378
|
-
|
|
8379
|
-
const
|
|
8380
|
-
|
|
8381
|
-
|
|
8382
|
-
|
|
8383
|
-
|
|
8384
|
-
|
|
8385
|
-
|
|
8386
|
-
|
|
8387
|
-
this.
|
|
8388
|
-
|
|
8389
|
-
|
|
8390
|
-
|
|
8391
|
-
|
|
8392
|
-
|
|
8393
|
-
|
|
8394
|
-
|
|
8395
|
-
|
|
8396
|
-
|
|
8397
|
-
|
|
8398
|
-
|
|
8399
|
-
|
|
8400
|
-
|
|
8401
|
-
|
|
8402
|
-
const slotIndex = this.dataPageManager.getNextSlotIndex(lastInsertDataPage, row);
|
|
8403
|
-
this.rowManager.setBodySize(row, data.length);
|
|
8404
|
-
this.rowManager.setBody(row, data);
|
|
8405
|
-
if (slotIndex === -1) {
|
|
8406
|
-
const newPageId = await this.pfs.appendNewPage(this.dataPageManager.pageType, tx);
|
|
8407
|
-
const newPage = await this.pfs.get(newPageId, tx);
|
|
8408
|
-
this.dataPageManager.insert(newPage, row);
|
|
8409
|
-
this.setRID(newPageId, 0);
|
|
8410
|
-
lastInsertDataPageId = newPageId;
|
|
8411
|
-
lastInsertDataPage = newPage;
|
|
8412
|
-
await this.pfs.setPage(newPageId, newPage, tx);
|
|
8383
|
+
for (const data of dataList) {
|
|
8384
|
+
const pk = ++lastPk;
|
|
8385
|
+
const willRowSize = this.getRequiredRowSize(data);
|
|
8386
|
+
if (willRowSize > this.maxBodySize || overflowForcly) {
|
|
8387
|
+
const overflowPageId = await this.pfs.appendNewPage(this.overflowPageManager.pageType, tx);
|
|
8388
|
+
const row = new Uint8Array(Row.CONSTANT.SIZE_HEADER + 4);
|
|
8389
|
+
this.rowManager.setPK(row, pk);
|
|
8390
|
+
this.rowManager.setOverflowFlag(row, true);
|
|
8391
|
+
this.rowManager.setBodySize(row, 4);
|
|
8392
|
+
this.rowManager.setBody(row, numberToBytes(overflowPageId, this.pageIdBuffer));
|
|
8393
|
+
const nextSlotIndex = this.dataPageManager.getNextSlotIndex(lastInsertDataPage, row);
|
|
8394
|
+
if (nextSlotIndex !== -1) {
|
|
8395
|
+
this.setRID(lastInsertDataPageId, nextSlotIndex);
|
|
8396
|
+
this.dataPageManager.insert(lastInsertDataPage, row);
|
|
8397
|
+
await this.pfs.setPage(lastInsertDataPageId, lastInsertDataPage, tx);
|
|
8398
|
+
} else {
|
|
8399
|
+
const newPageId = await this.pfs.appendNewPage(this.dataPageManager.pageType, tx);
|
|
8400
|
+
const newPage = await this.pfs.get(newPageId, tx);
|
|
8401
|
+
this.dataPageManager.insert(newPage, row);
|
|
8402
|
+
this.setRID(newPageId, 0);
|
|
8403
|
+
lastInsertDataPageId = newPageId;
|
|
8404
|
+
lastInsertDataPage = newPage;
|
|
8405
|
+
await this.pfs.setPage(newPageId, newPage, tx);
|
|
8406
|
+
}
|
|
8407
|
+
await this.pfs.writePageContent(overflowPageId, data, 0, tx);
|
|
8413
8408
|
} else {
|
|
8414
|
-
|
|
8415
|
-
this.
|
|
8416
|
-
|
|
8409
|
+
const row = new Uint8Array(Row.CONSTANT.SIZE_HEADER + data.length);
|
|
8410
|
+
const slotIndex = this.dataPageManager.getNextSlotIndex(lastInsertDataPage, row);
|
|
8411
|
+
this.rowManager.setBodySize(row, data.length);
|
|
8412
|
+
this.rowManager.setBody(row, data);
|
|
8413
|
+
if (slotIndex === -1) {
|
|
8414
|
+
const newPageId = await this.pfs.appendNewPage(this.dataPageManager.pageType, tx);
|
|
8415
|
+
const newPage = await this.pfs.get(newPageId, tx);
|
|
8416
|
+
this.dataPageManager.insert(newPage, row);
|
|
8417
|
+
this.setRID(newPageId, 0);
|
|
8418
|
+
lastInsertDataPageId = newPageId;
|
|
8419
|
+
lastInsertDataPage = newPage;
|
|
8420
|
+
await this.pfs.setPage(newPageId, newPage, tx);
|
|
8421
|
+
} else {
|
|
8422
|
+
this.dataPageManager.insert(lastInsertDataPage, row);
|
|
8423
|
+
this.setRID(lastInsertDataPageId, slotIndex);
|
|
8424
|
+
await this.pfs.setPage(lastInsertDataPageId, lastInsertDataPage, tx);
|
|
8425
|
+
}
|
|
8417
8426
|
}
|
|
8427
|
+
await btx.insert(this.getRID(), pk);
|
|
8428
|
+
pks.push(pk);
|
|
8418
8429
|
}
|
|
8430
|
+
tx.__markBPTreeDirty();
|
|
8419
8431
|
const freshMetadataPage = await this.pfs.getMetadata(tx);
|
|
8420
8432
|
this.metadataPageManager.setLastInsertPageId(freshMetadataPage, lastInsertDataPageId);
|
|
8421
|
-
this.metadataPageManager.setLastRowPk(freshMetadataPage,
|
|
8433
|
+
this.metadataPageManager.setLastRowPk(freshMetadataPage, lastPk);
|
|
8422
8434
|
if (incrementRowCount) {
|
|
8423
8435
|
const currentRowCount = this.metadataPageManager.getRowCount(freshMetadataPage);
|
|
8424
|
-
this.metadataPageManager.setRowCount(freshMetadataPage, currentRowCount +
|
|
8436
|
+
this.metadataPageManager.setRowCount(freshMetadataPage, currentRowCount + pks.length);
|
|
8425
8437
|
}
|
|
8426
8438
|
await this.pfs.setMetadata(freshMetadataPage, tx);
|
|
8427
|
-
|
|
8428
|
-
await btx.insert(this.getRID(), pk);
|
|
8429
|
-
tx.__markBPTreeDirty();
|
|
8430
|
-
return pk;
|
|
8439
|
+
return pks;
|
|
8431
8440
|
}
|
|
8432
8441
|
/**
|
|
8433
8442
|
* Looks up the RID by PK.
|
|
@@ -9099,12 +9108,13 @@ var DataplyAPI = class {
|
|
|
9099
9108
|
if (!this.initialized) {
|
|
9100
9109
|
throw new Error("Dataply instance is not initialized");
|
|
9101
9110
|
}
|
|
9102
|
-
return this.runWithDefault((tx2) => {
|
|
9111
|
+
return this.runWithDefault(async (tx2) => {
|
|
9103
9112
|
incrementRowCount = incrementRowCount ?? true;
|
|
9104
9113
|
if (typeof data === "string") {
|
|
9105
9114
|
data = this.textCodec.encode(data);
|
|
9106
9115
|
}
|
|
9107
|
-
|
|
9116
|
+
const pks = await this.rowTableEngine.insert([data], incrementRowCount, false, tx2);
|
|
9117
|
+
return pks[0];
|
|
9108
9118
|
}, tx);
|
|
9109
9119
|
}
|
|
9110
9120
|
/**
|
|
@@ -9118,12 +9128,13 @@ var DataplyAPI = class {
|
|
|
9118
9128
|
if (!this.initialized) {
|
|
9119
9129
|
throw new Error("Dataply instance is not initialized");
|
|
9120
9130
|
}
|
|
9121
|
-
return this.runWithDefault((tx2) => {
|
|
9131
|
+
return this.runWithDefault(async (tx2) => {
|
|
9122
9132
|
incrementRowCount = incrementRowCount ?? true;
|
|
9123
9133
|
if (typeof data === "string") {
|
|
9124
9134
|
data = this.textCodec.encode(data);
|
|
9125
9135
|
}
|
|
9126
|
-
|
|
9136
|
+
const pks = await this.rowTableEngine.insert([data], incrementRowCount, true, tx2);
|
|
9137
|
+
return pks[0];
|
|
9127
9138
|
}, tx);
|
|
9128
9139
|
}
|
|
9129
9140
|
/**
|
|
@@ -9140,13 +9151,10 @@ var DataplyAPI = class {
|
|
|
9140
9151
|
}
|
|
9141
9152
|
return this.runWithDefault(async (tx2) => {
|
|
9142
9153
|
incrementRowCount = incrementRowCount ?? true;
|
|
9143
|
-
const
|
|
9144
|
-
|
|
9145
|
-
|
|
9146
|
-
|
|
9147
|
-
pks.push(pk);
|
|
9148
|
-
}
|
|
9149
|
-
return pks;
|
|
9154
|
+
const encodedList = dataList.map(
|
|
9155
|
+
(data) => typeof data === "string" ? this.textCodec.encode(data) : data
|
|
9156
|
+
);
|
|
9157
|
+
return this.rowTableEngine.insert(encodedList, incrementRowCount, false, tx2);
|
|
9150
9158
|
}, tx);
|
|
9151
9159
|
}
|
|
9152
9160
|
/**
|
|
@@ -69,13 +69,14 @@ export declare class RowTableEngine {
|
|
|
69
69
|
*/
|
|
70
70
|
getMetadata(tx: Transaction): Promise<DataplyMetadata>;
|
|
71
71
|
/**
|
|
72
|
-
* Inserts data.
|
|
73
|
-
* @param data
|
|
72
|
+
* Inserts data (batch insert).
|
|
73
|
+
* @param dataList Array of data to insert
|
|
74
74
|
* @param incrementRowCount Whether to increment the row count to metadata
|
|
75
|
+
* @param overflowForcly Force overflow page creation for all data
|
|
75
76
|
* @param tx Transaction
|
|
76
|
-
* @returns
|
|
77
|
+
* @returns Array of PKs of the inserted data
|
|
77
78
|
*/
|
|
78
|
-
insert(
|
|
79
|
+
insert(dataList: Uint8Array[], incrementRowCount: boolean, overflowForcly: boolean, tx: Transaction): Promise<number[]>;
|
|
79
80
|
/**
|
|
80
81
|
* Looks up the RID by PK.
|
|
81
82
|
* Checks Pending Updates first if a transaction exists.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dataply",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.18-alpha.1",
|
|
4
4
|
"description": "A lightweight storage engine for Node.js with support for MVCC, WAL.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "izure <admin@izure.org>",
|
|
@@ -49,6 +49,6 @@
|
|
|
49
49
|
"hookall": "^2.2.0",
|
|
50
50
|
"mvcc-api": "^1.2.9",
|
|
51
51
|
"ryoiki": "^1.2.0",
|
|
52
|
-
"serializable-bptree": "^8.0.
|
|
52
|
+
"serializable-bptree": "^8.0.2"
|
|
53
53
|
}
|
|
54
54
|
}
|
package/readme.md
CHANGED
|
@@ -283,15 +283,15 @@ Dataply is optimized for high-speed data processing. Below are the results of ba
|
|
|
283
283
|
|
|
284
284
|
| Test Case | Count | Total Time | OPS (Operations Per Second) |
|
|
285
285
|
| :--- | :--- | :--- | :--- |
|
|
286
|
-
| **Bulk Insert (Batch)** | 10,000 | ~
|
|
287
|
-
| **Bulk Insert (Individual)** | 100 | ~
|
|
288
|
-
| **Bulk Insert with WAL** | 100 | ~
|
|
289
|
-
| **Medium Row Insert (1KB)** | 100 | ~
|
|
286
|
+
| **Bulk Insert (Batch)** | 10,000 | ~438ms | **~24,361 OPS** |
|
|
287
|
+
| **Bulk Insert (Individual)** | 100 | ~122ms | **~851 OPS** |
|
|
288
|
+
| **Bulk Insert with WAL** | 100 | ~118ms | **~891 OPS** |
|
|
289
|
+
| **Medium Row Insert (1KB)** | 100 | ~137ms | **~776 OPS** |
|
|
290
290
|
|
|
291
291
|
### Benchmark Analysis
|
|
292
|
-
- **Batching Efficiency**: Grouping operations into a single transaction is approximately **
|
|
293
|
-
- **WAL Trade-off**: Enabling Write-Ahead Logging ensures data durability
|
|
294
|
-
- **Node.js Optimization**: Dataply is designed to provide competitive performance (over **
|
|
292
|
+
- **Batching Efficiency**: Grouping operations into a single transaction is approximately **28.6x faster** than individual inserts by minimizing internal transaction management overhead.
|
|
293
|
+
- **WAL Trade-off**: Enabling Write-Ahead Logging ensures data durability. In this run, WAL performance was comparable to (and slightly faster than) individual inserts, demonstrating efficient logging overhead.
|
|
294
|
+
- **Node.js Optimization**: Dataply is designed to provide competitive performance (over **24,000 OPS** in batch mode) for a pure TypeScript Record Store without native dependencies.
|
|
295
295
|
|
|
296
296
|
> [!NOTE]
|
|
297
297
|
> Tests were conducted on a standard local environment (Node.js v25+). Performance may vary depending on hardware specifications (especially SSD/HDD) and system load.
|