Skip to content

Remove slower defer calls to improve INSERT performance #22

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/four-meals-grab.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@journeyapps/react-native-quick-sqlite': patch
---

This pull request improves the performance of releasing lock operations. Executing multiple lock operations, such as individual calls to `.execute`, should see a significant performance improvement.
12 changes: 5 additions & 7 deletions src/setup-open.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,6 @@ global.onLockContextIsAvailable = async (dbName: string, lockId: ContextLockID)
});
} catch (ex) {
console.error(ex);
} finally {
// Always release a lock once finished
closeContextLock(dbName, lockId);
}
});
};
Expand Down Expand Up @@ -119,12 +116,13 @@ export function setupOpen(QuickSQLite: ISQLite) {
await hooks?.lockAcquired?.();
const res = await callback(context);

// Ensure that we only resolve after locks are freed
_.defer(() => resolve(res));
closeContextLock(dbName, id);
resolve(res)
} catch (ex) {
_.defer(() => reject(ex));
closeContextLock(dbName, id);
reject(ex)
} finally {
_.defer(() => hooks?.lockReleased?.());
hooks?.lockReleased?.()
}
}
} as LockCallbackRecord);
Expand Down
20 changes: 20 additions & 0 deletions tests/tests/sqlite/rawQueries.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
} from 'react-native-quick-sqlite';
import { beforeEach, describe, it } from '../mocha/MochaRNAdapter';
import chai from 'chai';
import { randomIntFromInterval, numberName } from './utils';

const { expect } = chai;
const chance = new Chance();
Expand Down Expand Up @@ -62,6 +63,8 @@ export function registerBaseTests() {

await db.execute('DROP TABLE IF EXISTS User; ');
await db.execute('CREATE TABLE User ( id INT PRIMARY KEY, name TEXT NOT NULL, age INT, networth REAL) STRICT;');

await db.execute('CREATE TABLE IF NOT EXISTS t1(id INTEGER PRIMARY KEY, a INTEGER, b INTEGER, c TEXT)');
} catch (e) {
console.warn('error on before each', e);
}
Expand Down Expand Up @@ -590,5 +593,22 @@ export function registerBaseTests() {

expect(result.rows?.length).to.equal(1);
});

it('10000 INSERTs', async () => {
let start = performance.now();
for (let i = 0; i < 1000; ++i) {
const n = randomIntFromInterval(0, 100000);
await db.execute(`INSERT INTO t1(a, b, c) VALUES(?, ?, ?)`, [
i + 1,
n,
numberName(n),
]);
}
await db.execute('PRAGMA wal_checkpoint(RESTART)');
let end = performance.now();
let duration = end - start;

expect(duration).lessThan(2000);
});
});
}
74 changes: 74 additions & 0 deletions tests/tests/sqlite/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
export function randomIntFromInterval(min: number, max: number) {
// min included and max excluded
return Math.random() * (max - min) + min;
}

export function numberName(n: number) {
if (n == 0) {
return 'zero';
}

let numberName: string[] = [];
let d43 = Math.floor(n / 1000);
if (d43 != 0) {
numberName.push(names100[d43]);
numberName.push('thousand');
n -= d43 * 1000;
}

let d2 = Math.floor(n / 100);
if (d2 != 0) {
numberName.push(names100[d2]);
numberName.push('hundred');
n -= d2 * 100;
}

let d10 = n;
if (d10 != 0) {
numberName.push(names100[d10]);
}

return numberName.join(' ');
}

export function assertAlways(condition: boolean) {
if (!condition) {
throw Error('Assertion failed');
}
}

const digits = [
'',
'one',
'two',
'three',
'four',
'five',
'six',
'seven',
'eight',
'nine',
];
const names100: string[] = [
...digits,
...[
'ten',
'eleven',
'twelve',
'thirteen',
'fourteen',
'fifteen',
'sixteen',
'seventeen',
'eighteen',
'nineteen',
],
...digits.map((digit) => `twenty${digit != '' ? '-' + digit : ''}`),
...digits.map((digit) => `thirty${digit != '' ? '-' + digit : ''}`),
...digits.map((digit) => `forty${digit != '' ? '-' + digit : ''}`),
...digits.map((digit) => `fifty${digit != '' ? '-' + digit : ''}`),
...digits.map((digit) => `sixty${digit != '' ? '-' + digit : ''}`),
...digits.map((digit) => `seventy${digit != '' ? '-' + digit : ''}`),
...digits.map((digit) => `eighty${digit != '' ? '-' + digit : ''}`),
...digits.map((digit) => `ninety${digit != '' ? '-' + digit : ''}`),
];