Skip to content

Commit bb65cfa

Browse files
authored
Allow profiling queries (#91)
* feat: Allow profiling queries * Use Homebrew SQLite if available * More web improvements * chore(release): publish packages - [email protected] - [email protected]+1 * Fix passing task to write context * Enable profiling by default * Add common prefix * Include prefix on web * Disable profiling on workers Browsers don't surface this information either way * Remove pubspec changes to drift_sqlite_async
1 parent 6d85217 commit bb65cfa

File tree

11 files changed

+337
-127
lines changed

11 files changed

+337
-127
lines changed

packages/sqlite_async/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.11.5
2+
3+
- Allow profiling queries.
4+
15
## 0.11.4
26

37
- Add `SqliteConnection.synchronousWrapper` and `SqliteDatabase.singleConnection`.

packages/sqlite_async/lib/src/common/connection/sync_sqlite_connection.dart

Lines changed: 60 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
import 'dart:developer';
2+
13
import 'package:sqlite3/common.dart';
24
import 'package:sqlite_async/src/common/mutex.dart';
35
import 'package:sqlite_async/src/sqlite_connection.dart';
6+
import 'package:sqlite_async/src/sqlite_options.dart';
47
import 'package:sqlite_async/src/sqlite_queries.dart';
58
import 'package:sqlite_async/src/update_notification.dart';
9+
import 'package:sqlite_async/src/utils/profiler.dart';
610

711
/// A simple "synchronous" connection which provides the async SqliteConnection
812
/// implementation using a synchronous SQLite connection
@@ -14,7 +18,15 @@ class SyncSqliteConnection extends SqliteConnection with SqliteQueries {
1418

1519
bool _closed = false;
1620

17-
SyncSqliteConnection(this.db, Mutex m) {
21+
/// Whether queries should be added to the `dart:developer` timeline.
22+
///
23+
/// This is enabled by default outside of release builds, see
24+
/// [SqliteOptions.profileQueries] for details.
25+
final bool profileQueries;
26+
27+
SyncSqliteConnection(this.db, Mutex m, {bool? profileQueries})
28+
: profileQueries =
29+
profileQueries ?? const SqliteOptions().profileQueries {
1830
mutex = m.open();
1931
updates = db.updates.map(
2032
(event) {
@@ -26,15 +38,31 @@ class SyncSqliteConnection extends SqliteConnection with SqliteQueries {
2638
@override
2739
Future<T> readLock<T>(Future<T> Function(SqliteReadContext tx) callback,
2840
{Duration? lockTimeout, String? debugContext}) {
29-
return mutex.lock(() => callback(SyncReadContext(db)),
30-
timeout: lockTimeout);
41+
final task = profileQueries ? TimelineTask() : null;
42+
task?.start('${profilerPrefix}mutex_lock');
43+
44+
return mutex.lock(
45+
() {
46+
task?.finish();
47+
return callback(SyncReadContext(db, parent: task));
48+
},
49+
timeout: lockTimeout,
50+
);
3151
}
3252

3353
@override
3454
Future<T> writeLock<T>(Future<T> Function(SqliteWriteContext tx) callback,
3555
{Duration? lockTimeout, String? debugContext}) {
36-
return mutex.lock(() => callback(SyncWriteContext(db)),
37-
timeout: lockTimeout);
56+
final task = profileQueries ? TimelineTask() : null;
57+
task?.start('${profilerPrefix}mutex_lock');
58+
59+
return mutex.lock(
60+
() {
61+
task?.finish();
62+
return callback(SyncWriteContext(db, parent: task));
63+
},
64+
timeout: lockTimeout,
65+
);
3866
}
3967

4068
@override
@@ -53,9 +81,12 @@ class SyncSqliteConnection extends SqliteConnection with SqliteQueries {
5381
}
5482

5583
class SyncReadContext implements SqliteReadContext {
84+
final TimelineTask? task;
85+
5686
CommonDatabase db;
5787

58-
SyncReadContext(this.db);
88+
SyncReadContext(this.db, {TimelineTask? parent})
89+
: task = TimelineTask(parent: parent);
5990

6091
@override
6192
Future<T> computeWithDatabase<T>(
@@ -65,13 +96,23 @@ class SyncReadContext implements SqliteReadContext {
6596

6697
@override
6798
Future<Row> get(String sql, [List<Object?> parameters = const []]) async {
68-
return db.select(sql, parameters).first;
99+
return task.timeSync(
100+
'get',
101+
() => db.select(sql, parameters).first,
102+
sql: sql,
103+
parameters: parameters,
104+
);
69105
}
70106

71107
@override
72108
Future<ResultSet> getAll(String sql,
73109
[List<Object?> parameters = const []]) async {
74-
return db.select(sql, parameters);
110+
return task.timeSync(
111+
'getAll',
112+
() => db.select(sql, parameters),
113+
sql: sql,
114+
parameters: parameters,
115+
);
75116
}
76117

77118
@override
@@ -91,26 +132,32 @@ class SyncReadContext implements SqliteReadContext {
91132
}
92133

93134
class SyncWriteContext extends SyncReadContext implements SqliteWriteContext {
94-
SyncWriteContext(super.db);
135+
SyncWriteContext(super.db, {super.parent});
95136

96137
@override
97138
Future<ResultSet> execute(String sql,
98139
[List<Object?> parameters = const []]) async {
99-
return db.select(sql, parameters);
140+
return task.timeSync(
141+
'execute',
142+
() => db.select(sql, parameters),
143+
sql: sql,
144+
parameters: parameters,
145+
);
100146
}
101147

102148
@override
103149
Future<void> executeBatch(
104150
String sql, List<List<Object?>> parameterSets) async {
105-
return computeWithDatabase((db) async {
151+
task.timeSync('executeBatch', () {
106152
final statement = db.prepare(sql, checkNoTail: true);
107153
try {
108154
for (var parameters in parameterSets) {
109-
statement.execute(parameters);
155+
task.timeSync('iteration', () => statement.execute(parameters),
156+
parameters: parameters);
110157
}
111158
} finally {
112159
statement.dispose();
113160
}
114-
});
161+
}, sql: sql);
115162
}
116163
}

0 commit comments

Comments
 (0)