Skip to content

Commit ec8957d

Browse files
authored
feat: add lovefield and sql.js (#16)
1 parent ef47f4f commit ec8957d

File tree

5 files changed

+136
-6
lines changed

5 files changed

+136
-6
lines changed

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
},
1313
"dependencies": {
1414
"@electron/remote": "2",
15+
"debug": "^4.3.4",
1516
"detect-port": "1",
1617
"electrom": "19",
1718
"electron": "19",
@@ -21,9 +22,11 @@
2122
"electron-windows-titlebar": "1",
2223
"graceful-updater": "1",
2324
"lodash": "4",
25+
"lovefield": "^2.1.12",
2426
"moment": "^2.29.4",
2527
"network-interface": "18",
2628
"semver": "^7.3.8",
29+
"sql.js": "^1.8.0",
2730
"windows-verify-trust": "1"
2831
},
2932
"optionalDependencies": {

src/local-storage/renderer/indexeddb-helper.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ window.indexedDBHelper = {
5959
},
6060
addBatchTestData: (objectStore, count = 1000) => {
6161
return new Promise((resolve, reject) => {
62+
console.time('addBatchTestData');
6263
for (let i = 1; i <= count; i++) {
6364
const data = {
6465
index1: `index_${i}`,
@@ -74,6 +75,7 @@ window.indexedDBHelper = {
7475
}
7576
objectStore.transaction.oncomplete = () => {
7677
console.log('Transaction completed');
78+
console.timeEnd('addBatchTestData');
7779
resolve(true);
7880
};
7981
objectStore.transaction.onerror = (event) => {

src/local-storage/renderer/main.html

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
66
<link rel="shortcut icon" href="#" />
77
<title>Storage Benchmarks</title>
8-
<script src="../../../node_modules/dexie/dist/dexie.js"></script>
9-
<script src="../../../node_modules/monitor.js/build/monitor.js"></script>
10-
<script src="./indexeddb-helper.js"></script>
118
<link rel="stylesheet" href="./main.css" />
129
</style>
1310
</head>
@@ -61,6 +58,15 @@
6158
/>
6259
<label for="db1-4">Dexie.js WebWorker</label>
6360
</div>
61+
<div>
62+
<input
63+
type="radio"
64+
id="db1-5"
65+
name="IndexedDB"
66+
value="LoveField"
67+
/>
68+
<label for="db1-5">LoveField</label>
69+
</div>
6470
</fieldset>
6571
</form>
6672
</div>
@@ -98,10 +104,18 @@
98104
type="radio"
99105
id="db2-3"
100106
name="SQLite"
101-
value="WebAssembly"
102-
disabled
107+
value="WASM"
103108
/>
104-
<label for="db2-3">WIP: WebAssembly</label>
109+
<label for="db2-3">sql.js with wasm</label>
110+
</div>
111+
<div>
112+
<input
113+
type="radio"
114+
id="db2-4"
115+
name="SQLite"
116+
value="WASMInWorker"
117+
/>
118+
<label for="db2-4">sql.js with wasm in worker</label>
105119
</div>
106120
</fieldset>
107121
</form>
@@ -132,6 +146,12 @@
132146
</ul>
133147
</div>
134148
</div>
149+
150+
<script src="../../../node_modules/dexie/dist/dexie.js"></script>
151+
<script src="../../../node_modules/lovefield/dist/lovefield.js"></script>
152+
<script src="../../../node_modules/sql.js/dist/sql-wasm.js"></script>
153+
<script src="../../../node_modules/monitor.js/build/monitor.js"></script>
154+
<script src="./indexeddb-helper.js"></script>
135155
<script src="./main.js"></script>
136156
</body>
137157
</html>

src/local-storage/renderer/main.js

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,111 @@ class MainApp {
110110
this.log(type, `end time: ${endTime}, use ${((endTime - startTime) / 1000).toFixed(2)}s`);
111111
}
112112

113+
async runIndexedDBLoveField(type) {
114+
await window.indexedDBHelper.deleteAllIndexedDB();
115+
116+
const schemaBuilder = lf.schema.create('todo', 1);
117+
schemaBuilder.createTable('Item')
118+
.addColumn('id', lf.Type.INTEGER)
119+
.addColumn('description', lf.Type.STRING)
120+
.addPrimaryKey(['id']);
121+
122+
const db = await schemaBuilder.connect();
123+
db.getSchema().table('Item');
124+
125+
const { count } = this.runnerConfig;
126+
const startTime = Date.now();
127+
this.log(type, `start time: ${startTime}, count: ${count}`);
128+
for (let i = 0; i < count; i++) {
129+
const item = db.getSchema().table('Item');
130+
const row = item.createRow({
131+
id: i,
132+
description: new Array(100).fill('测试').join(''),
133+
});
134+
135+
await db.insertOrReplace().into(item).values([row]).exec();
136+
137+
console.log('Data added successfully');
138+
}
139+
const endTime = Date.now();
140+
this.log(type, `end time: ${endTime}, use ${((endTime - startTime) / 1000).toFixed(2)}s`);
141+
}
142+
143+
async runSQLiteWASM(type) {
144+
const SQL = await initSqlJs({
145+
// Required to load the wasm binary asynchronously. Of course, you can host it wherever you want
146+
// You can omit locateFile completely when running in node
147+
locateFile: () => '../../../node_modules/sql.js/dist/sql-wasm.wasm',
148+
});
149+
150+
const db = new SQL.Database();
151+
db.run('DROP TABLE IF EXISTS todo');
152+
db.run('CREATE TABLE todo (id int, description varchar);');
153+
154+
const { count } = this.runnerConfig;
155+
const startTime = Date.now();
156+
this.log(type, `start time: ${startTime}, count: ${count}`);
157+
for (let i = 0; i < count; i++) {
158+
db.run('INSERT INTO todo VALUES (?,?)', [i, new Array(100).fill('测试').join('')]);
159+
console.log('Data added successfully');
160+
}
161+
const endTime = Date.now();
162+
this.log(type, `end time: ${endTime}, use ${((endTime - startTime) / 1000).toFixed(2)}s`);
163+
}
164+
165+
async runSQLiteWASMInWorker(type) {
166+
const worker = new Worker('../../../node_modules/sql.js/dist/worker.sql-wasm.js');
167+
168+
worker.onmessage = () => {
169+
console.log('Database opened');
170+
worker.onmessage = event => {
171+
console.log('Data added successfully');
172+
if (event.data?.id === 'end') {
173+
const endTime = Date.now();
174+
this.log(type, `end time: ${endTime}, use ${((endTime - startTime) / 1000).toFixed(2)}s`);
175+
}
176+
};
177+
178+
worker.postMessage({
179+
id: 'drop',
180+
action: 'exec',
181+
sql: 'DROP TABLE IF EXISTS todo_worker',
182+
});
183+
184+
// create table
185+
worker.postMessage({
186+
id: 'init',
187+
action: 'exec',
188+
sql: 'CREATE TABLE todo_worker (id int, description varchar);',
189+
});
190+
191+
const { count } = this.runnerConfig;
192+
const startTime = Date.now();
193+
this.log(type, `start time: ${startTime}, count: ${count}`);
194+
for (let i = 0; i < count; i++) {
195+
worker.postMessage({
196+
id: i,
197+
action: 'exec',
198+
sql: 'INSERT INTO todo_worker VALUES ($id, $description)',
199+
params: { $id: i, $description: new Array(100).fill('测试').join('') },
200+
});
201+
}
202+
203+
// 以 count 结束
204+
worker.postMessage({
205+
id: 'end',
206+
action: 'exec',
207+
sql: 'select count(*) from todo_worker',
208+
});
209+
};
210+
211+
worker.onerror = e => console.log('Worker error: ', e);
212+
worker.postMessage({
213+
id: 'open',
214+
action: 'open',
215+
});
216+
}
217+
113218
async runSQLiteElectronNative(type) {
114219
const { count } = this.runnerConfig;
115220
const startTime = Date.now();

test.db

Whitespace-only changes.

0 commit comments

Comments
 (0)