Compare commits

...
Sign in to create a new pull request.

2 commits

Author SHA1 Message Date
f1a3c0a8cf TODO Debug sqlite performance 2025-02-21 00:32:48 +01:00
40814a7efb TODO Update dependencies 2025-02-21 00:32:48 +01:00
3 changed files with 325 additions and 376 deletions

597
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -7,43 +7,49 @@ version = "0.8.3"
edition = "2021" edition = "2021"
[workspace.dependencies] [workspace.dependencies]
anyhow = "1.0.86" anyhow = "1.0.96"
async-trait = "0.1.80" async-trait = "0.1.86"
clap = { version = "4.5.4", features = ["derive", "deprecated"] } clap = { version = "4.5.30", features = ["derive", "deprecated"] }
cookie = "0.18.1" cookie = "0.18.1"
crossterm = "0.27.0" crossterm = "0.28.1"
directories = "5.0.1" directories = "6.0.0"
edit = "0.1.5" edit = "0.1.5"
jiff = "0.2.1" jiff = "0.2.1"
linkify = "0.10.0" linkify = "0.10.0"
log = { version = "0.4.21", features = ["std"] } log = { version = "0.4.25", features = ["std"] }
once_cell = "1.19.0" once_cell = "1.20.2"
open = "5.1.3" open = "5.3.2"
parking_lot = "0.12.2" parking_lot = "0.12.3"
proc-macro2 = "1.0.83" proc-macro2 = "1.0.93"
quote = "1.0.36" quote = "1.0.38"
rusqlite = { version = "0.31.0", features = ["bundled", "time"] } rusqlite = { version = "0.31.0", features = [
rustls = "0.23.19" # "bundled",
serde = { version = "1.0.202", features = ["derive"] } "time",
] }
rustls = "0.23.23"
serde = { version = "1.0.218", features = ["derive"] }
serde_either = "0.2.1" serde_either = "0.2.1"
serde_json = "1.0.117" serde_json = "1.0.139"
syn = "2.0.65" syn = "2.0.98"
thiserror = "1.0.61" thiserror = "2.0.11"
tokio = { version = "1.37.0", features = ["full"] } tokio = { version = "1.43.0", features = ["full"] }
toml = "0.8.13" toml = "0.8.20"
unicode-width = "0.1.12" unicode-width = "0.2.0"
[workspace.dependencies.euphoxide] [workspace.dependencies.euphoxide]
git = "https://github.com/Garmelon/euphoxide.git" path = "../euphoxide"
# git = "https://github.com/Garmelon/euphoxide.git"
features = ["bot"] features = ["bot"]
[workspace.dependencies.toss] [workspace.dependencies.toss]
git = "https://github.com/Garmelon/toss.git" path = "../toss"
tag = "v0.2.3" # git = "https://github.com/Garmelon/toss.git"
# tag = "v0.2.3"
[workspace.dependencies.vault] [workspace.dependencies.vault]
git = "https://github.com/Garmelon/vault.git" path = "../vault"
tag = "v0.4.0" # git = "https://github.com/Garmelon/vault.git"
# tag = "v0.5.0"
features = ["tokio"] features = ["tokio"]
[workspace.lints] [workspace.lints]
@ -71,3 +77,11 @@ clippy.use_self = "warn"
[profile.dev.package."*"] [profile.dev.package."*"]
opt-level = 3 opt-level = 3
# For profiling
[profile.release]
debug = 1
[rust]
debuginfo-level = 1

View file

@ -1,4 +1,5 @@
use std::str::FromStr; use std::str::FromStr;
use std::time::Instant;
use std::{fmt, mem}; use std::{fmt, mem};
use async_trait::async_trait; use async_trait::async_trait;
@ -686,12 +687,12 @@ impl Action for GetTree {
type Error = rusqlite::Error; type Error = rusqlite::Error;
fn run(self, conn: &mut Connection) -> Result<Self::Output, Self::Error> { fn run(self, conn: &mut Connection) -> Result<Self::Output, Self::Error> {
let msgs = conn let start = Instant::now();
.prepare(
" let query = "
WITH RECURSIVE WITH RECURSIVE
tree (domain, room, id) AS ( tree (domain, room, id) AS (
VALUES (?, ?, ?) VALUES (:domain, :room, :id)
UNION UNION
SELECT euph_msgs.domain, euph_msgs.room, euph_msgs.id SELECT euph_msgs.domain, euph_msgs.room, euph_msgs.id
FROM euph_msgs FROM euph_msgs
@ -700,14 +701,35 @@ impl Action for GetTree {
AND tree.room = euph_msgs.room AND tree.room = euph_msgs.room
AND tree.id = euph_msgs.parent AND tree.id = euph_msgs.parent
) )
SELECT id, parent, time, name, content, seen SELECT id, parent, time, 'name', 'content', 1
FROM euph_msgs FROM euph_msgs
JOIN tree USING (domain, room, id) JOIN tree USING (domain, room, id)
ORDER BY id ASC ORDER BY id ASC
", ";
)?
let mut statement = conn.prepare(&format!("EXPLAIN QUERY PLAN {query}"))?;
let mut rows = statement.query(named_params! {
":domain": self.room.domain,
":room": self.room.name,
":id": WSnowflake(self.root_id.0),
})?;
while let Some(row) = rows.next()? {
let id = row.get::<_, i64>("id")?;
let parent = row.get::<_, i64>("parent")?;
let notused = row.get::<_, i64>("notused")?;
let detail = row.get::<_, String>("detail")?;
eprintln!("{parent:3} -> {id:3} (notused {notused:3}): {detail}");
}
let msgs = conn
.prepare(query)?
.query_map( .query_map(
params![self.room.domain, self.room.name, WSnowflake(self.root_id.0)], named_params! {
":domain": self.room.domain,
":room": self.room.name,
":id": WSnowflake(self.root_id.0),
},
|row| { |row| {
Ok(SmallMessage { Ok(SmallMessage {
id: MessageId(row.get::<_, WSnowflake>(0)?.0), id: MessageId(row.get::<_, WSnowflake>(0)?.0),
@ -720,6 +742,8 @@ impl Action for GetTree {
}, },
)? )?
.collect::<rusqlite::Result<_>>()?; .collect::<rusqlite::Result<_>>()?;
let end = Instant::now();
eprintln!("{:10}", end.duration_since(start).as_micros());
Ok(Tree::new(self.root_id, msgs)) Ok(Tree::new(self.root_id, msgs))
} }
} }