mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2026-11-06 16:07:50 +00:00
This puts a lot of state into a new `LockedStream` that was formerly guarded more coarsely by the recording lock or more granularly by `RecordingToInsert` locks. And it restructures `LockedDatabase::flush` to avoid holding this lock while performing SQLite operations. Streamers write only into a recent frames buffer in RAM, which the directory pool workers asynchronously write to disk approximately once per GOP, where formerly there was a write call per frame. Before, streamers could fall behind due to slow sample file directory disk I/O calls or if writing got stuck in a retry loop, for example if out of disk space. If Moonfire falls too far behind in receiving, cameras tend to disconnect or (sadly) mis-frame messages because they do not handle this case well. This removes a confusing potential cause of such errors. In the new model, streamers never wait for disk I/O. Frames are buffered up to a limit. Recordings are aborted if the I/O pool falls too far behind. There's no retry loop. This roughly halves CPU usage as thread hand-offs and syscalls are less common. It also enables several desirable future changes: * audio recording (which radically increases the number of frames and thus would otherwise significantly increase CPU usage). * "monitor mode" (allowing live view without recording to disk), * further CPU reductions for live view (by skipping all SQLite ops and disk I/O). In the new model, streamers also rarely wait for SQLite database operations either—now only on video parameter changes. That might go away in an upcoming change too. The "syncer" (which synced files/dirs and kept track of what has to be flushed into the SQLite database when) has mostly gone away too. The directory pool workers handle the syncing now, and then they notify a new "flusher" for the latter portion. I'd like to go further still and have the database as a whole be owned by a dedicated thread, the only one that uses the SQLite connection. This prevents the tokio threads from blocking on SQLite operations. I tried out doing so before making the streamers less dependent on the db, but the extra thread handoffs were awful for performance.
54 lines
1.2 KiB
TOML
54 lines
1.2 KiB
TOML
[package]
|
|
name = "moonfire-db"
|
|
version = "0.0.0"
|
|
authors = ["Scott Lamb <slamb@slamb.org>"]
|
|
readme = "../README.md"
|
|
edition = "2021"
|
|
license-file = "../../LICENSE.txt"
|
|
rust-version = "1.91"
|
|
publish = false
|
|
|
|
[features]
|
|
nightly = []
|
|
|
|
[lib]
|
|
path = "lib.rs"
|
|
|
|
[dependencies]
|
|
arrayvec = "0.7.6"
|
|
base = { package = "moonfire-base", path = "../base" }
|
|
base64 = { workspace = true }
|
|
bitflags = "2.9.0"
|
|
blake3 = "1.0.0"
|
|
byteorder = "1.0"
|
|
bytes = { workspace = true }
|
|
derive_more.workspace = true
|
|
diff = "0.1.12"
|
|
futures = "0.3"
|
|
h264-reader = { workspace = true }
|
|
hashlink = "0.10.0"
|
|
itertools = { workspace = true }
|
|
jiff = { workspace = true }
|
|
libc = "0.2"
|
|
nix = { workspace = true, features = ["dir", "feature", "fs", "mman"] }
|
|
num-rational = { version = "0.4.0", default-features = false, features = [
|
|
"std",
|
|
] }
|
|
pretty-hex = { workspace = true }
|
|
protobuf.workspace = true
|
|
reffers.workspace = true
|
|
ring = { workspace = true }
|
|
rusqlite = { workspace = true }
|
|
scrypt = "0.11.0"
|
|
serde = { version = "1.0", features = ["derive"] }
|
|
serde_json = "1.0"
|
|
smallvec = "1.0"
|
|
tempfile = "3.2.0"
|
|
tokio = { workspace = true }
|
|
tracing = { workspace = true }
|
|
url = { version = "2.1.1", features = ["serde"] }
|
|
uuid = { workspace = true }
|
|
|
|
[build-dependencies]
|
|
protobuf-codegen = { workspace = true }
|