-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
SQLite step serialization overhead #1175
Comments
To not block the current thread assuming you are in an async IO environment. The only reason there is a synchronization block is we are trying to do "zero-copy" SQLite which I think we need to move away from. Rusqlite buffers the SQLite row into a separate data type before handing it to you. If we did this, there would be no real sync overhead. Additionally, in |
I have tried moving diff --git a/sqlx-core/src/sqlite/connection/executor.rs b/sqlx-core/src/sqlite/connection/executor.rs
index 6e09fdc2..31dd961e 100644
--- a/sqlx-core/src/sqlite/connection/executor.rs
+++ b/sqlx-core/src/sqlite/connection/executor.rs
@@ -12,7 +12,7 @@ use crate::sqlite::{
use either::Either;
use futures_core::future::BoxFuture;
use futures_core::stream::BoxStream;
-use libsqlite3_sys::sqlite3_last_insert_rowid;
+use libsqlite3_sys::{sqlite3_step, sqlite3_last_insert_rowid, SQLITE_DONE, SQLITE_ROW};
use std::borrow::Cow;
use std::sync::Arc;
@@ -125,7 +125,16 @@ impl<'c> Executor<'c> for &'c mut SqliteConnection {
// invoke [sqlite3_step] on the dedicated worker thread
// this will move us forward one row or finish the statement
- let s = worker.step(*stmt).await?;
+ let time_start = std::time::SystemTime::now();
+ let status = unsafe { sqlite3_step(stmt.0.as_ptr()) };
+ let resp: Result<Either<u64, ()>, Error> = match status {
+ SQLITE_ROW => Ok(Either::Right(())),
+ SQLITE_DONE => Ok(Either::Left(stmt.changes())),
+ _ => Err(stmt.last_error().into()),
+ };
+ let s = resp?;
+
+ //println!("worker: {:.3?}", time_start.elapsed().unwrap());
match s {
Either::Left(changes) => { It only cuts around ~10ms in total for my statement returning 131 rows, so it is probably not the major cause of latency. I still have time jumping between ~70ms and about ~130ms when I execute the same statement. Anyway, maybe instead of serializing every step it makes sense to just start the worker and let it run |
Yep. The channel approach is exactly how I'm thinking it should be. |
Could you try your benchmark with the changes I have in #1551 to see if there's any improvement? |
I have added the following profiling to f7775f7 (tag
v0.5.2
):Executing a single statement returning multiple rows, I see a large per-row overhead:
Overhead of about 0.1ms per row just to wait for the kernel to give some time to another thread instead of doing
sqlite3_step
ourselves is a lot and causes a visible performance degradation compared torusqilte
+r2d2
: deltachat/deltachat-core-rust#2353What is the point of having a separate thread to execute
sqlite3_step
?The text was updated successfully, but these errors were encountered: