-
Notifications
You must be signed in to change notification settings - Fork 373
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SDK: stream to disk with
save
feature (#1405)
* Refactor LogMsg-encoder to be a `struct` * Small cleanup of Sender * Refactor Session: extract the web-viewer connection * Refactor Session::connect * Log SDK: stream log data to file on disk * Rust examples: --save streams to disk * Python examples: start streaming to disk right away * typo Co-authored-by: Clement Rey <[email protected]> --------- Co-authored-by: Clement Rey <[email protected]>
- Loading branch information
Showing
10 changed files
with
241 additions
and
146 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
use anyhow::Context as _; | ||
|
||
use re_log_types::LogMsg; | ||
|
||
pub struct FileWriter { | ||
// None = quit | ||
tx: std::sync::mpsc::Sender<Option<LogMsg>>, | ||
join_handle: Option<std::thread::JoinHandle<()>>, | ||
} | ||
|
||
impl Drop for FileWriter { | ||
fn drop(&mut self) { | ||
self.tx.send(None).ok(); | ||
if let Some(join_handle) = self.join_handle.take() { | ||
join_handle.join().ok(); | ||
} | ||
} | ||
} | ||
|
||
impl FileWriter { | ||
pub fn new(path: impl Into<std::path::PathBuf>) -> anyhow::Result<Self> { | ||
let (tx, rx) = std::sync::mpsc::channel(); | ||
|
||
let path = path.into(); | ||
|
||
re_log::debug!("Saving file to {path:?}…"); | ||
|
||
let file = std::fs::File::create(&path).with_context(|| format!("Path: {:?}", path))?; | ||
let mut encoder = re_log_types::encoding::Encoder::new(file)?; | ||
|
||
let join_handle = std::thread::Builder::new() | ||
.name("file_writer".into()) | ||
.spawn(move || { | ||
while let Ok(Some(log_msg)) = rx.recv() { | ||
if let Err(err) = encoder.append(&log_msg) { | ||
re_log::error!("Failed to save log stream to {path:?}: {err}"); | ||
return; | ||
} | ||
} | ||
if let Err(err) = encoder.finish() { | ||
re_log::error!("Failed to save log stream to {path:?}: {err}"); | ||
} else { | ||
re_log::debug!("Log stream saved to {path:?}"); | ||
} | ||
}) | ||
.context("Failed to spawn thread")?; | ||
|
||
Ok(Self { | ||
tx, | ||
join_handle: Some(join_handle), | ||
}) | ||
} | ||
|
||
pub fn write(&self, msg: LogMsg) { | ||
self.tx.send(Some(msg)).ok(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
use re_log_types::LogMsg; | ||
|
||
/// Hosts two servers: | ||
/// * A web-server, serving the web-viewer | ||
/// * A `WebSocket` server, server [`LogMsg`]es to remote viewer(s). | ||
pub struct RemoteViewerServer { | ||
web_server_join_handle: tokio::task::JoinHandle<()>, | ||
sender: re_smart_channel::Sender<LogMsg>, | ||
} | ||
|
||
impl Drop for RemoteViewerServer { | ||
fn drop(&mut self) { | ||
re_log::info!("Shutting down web server."); | ||
self.web_server_join_handle.abort(); | ||
} | ||
} | ||
|
||
impl RemoteViewerServer { | ||
pub fn new(tokio_rt: &tokio::runtime::Runtime, open_browser: bool) -> Self { | ||
let (rerun_tx, rerun_rx) = re_smart_channel::smart_channel(re_smart_channel::Source::Sdk); | ||
|
||
let web_server_join_handle = tokio_rt.spawn(async move { | ||
// This is the server which the web viewer will talk to: | ||
let ws_server = re_ws_comms::Server::new(re_ws_comms::DEFAULT_WS_SERVER_PORT) | ||
.await | ||
.unwrap(); | ||
let ws_server_handle = tokio::spawn(ws_server.listen(rerun_rx)); // TODO(emilk): use tokio_rt ? | ||
|
||
// This is the server that serves the Wasm+HTML: | ||
let web_port = 9090; | ||
let web_server = re_web_server::WebServer::new(web_port); | ||
let web_server_handle = tokio::spawn(async move { | ||
web_server.serve().await.unwrap(); | ||
}); | ||
|
||
let ws_server_url = re_ws_comms::default_server_url(); | ||
let viewer_url = format!("http://127.0.0.1:{web_port}?url={ws_server_url}"); | ||
if open_browser { | ||
webbrowser::open(&viewer_url).ok(); | ||
} else { | ||
re_log::info!("Web server is running - view it at {viewer_url}"); | ||
} | ||
|
||
ws_server_handle.await.unwrap().unwrap(); | ||
web_server_handle.await.unwrap(); | ||
}); | ||
|
||
Self { | ||
web_server_join_handle, | ||
sender: rerun_tx, | ||
} | ||
} | ||
|
||
pub fn send(&self, msg: LogMsg) { | ||
if let Err(err) = self.sender.send(msg) { | ||
re_log::error_once!("Failed to send log message to web server: {err}"); | ||
} | ||
} | ||
} |
Oops, something went wrong.
c97747a
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rust Benchmark
datastore/insert/batch/rects/insert
562683
ns/iter (± 5452
)547348
ns/iter (± 2815
)1.03
datastore/latest_at/batch/rects/query
1872
ns/iter (± 11
)1830
ns/iter (± 5
)1.02
datastore/latest_at/missing_components/primary
352
ns/iter (± 3
)358
ns/iter (± 0
)0.98
datastore/latest_at/missing_components/secondaries
413
ns/iter (± 5
)425
ns/iter (± 2
)0.97
datastore/range/batch/rects/query
152009
ns/iter (± 1789
)152112
ns/iter (± 580
)1.00
mono_points_arrow/generate_message_bundles
43940291
ns/iter (± 1271642
)45855910
ns/iter (± 840388
)0.96
mono_points_arrow/generate_messages
124306090
ns/iter (± 1361079
)125104798
ns/iter (± 1052527
)0.99
mono_points_arrow/encode_log_msg
148283826
ns/iter (± 1441515
)152105812
ns/iter (± 1019000
)0.97
mono_points_arrow/encode_total
322695077
ns/iter (± 3011993
)326032772
ns/iter (± 1243889
)0.99
mono_points_arrow/decode_log_msg
172713411
ns/iter (± 1540497
)177194253
ns/iter (± 828451
)0.97
mono_points_arrow/decode_message_bundles
62192589
ns/iter (± 782759
)64301048
ns/iter (± 714563
)0.97
mono_points_arrow/decode_total
233713482
ns/iter (± 2179769
)238352334
ns/iter (± 1853136
)0.98
batch_points_arrow/generate_message_bundles
328899
ns/iter (± 3928
)325314
ns/iter (± 1175
)1.01
batch_points_arrow/generate_messages
6101
ns/iter (± 62
)6245
ns/iter (± 33
)0.98
batch_points_arrow/encode_log_msg
370951
ns/iter (± 3365
)373141
ns/iter (± 1733
)0.99
batch_points_arrow/encode_total
710103
ns/iter (± 6365
)715043
ns/iter (± 2797
)0.99
batch_points_arrow/decode_log_msg
350493
ns/iter (± 2018
)350709
ns/iter (± 1761
)1.00
batch_points_arrow/decode_message_bundles
2023
ns/iter (± 16
)2031
ns/iter (± 12
)1.00
batch_points_arrow/decode_total
354190
ns/iter (± 1031
)356021
ns/iter (± 1070
)0.99
arrow_mono_points/insert
6054023341
ns/iter (± 22243189
)6105989507
ns/iter (± 13623479
)0.99
arrow_mono_points/query
1703940
ns/iter (± 23239
)1737889
ns/iter (± 10434
)0.98
arrow_batch_points/insert
2660869
ns/iter (± 28520
)2679472
ns/iter (± 10887
)0.99
arrow_batch_points/query
17451
ns/iter (± 177
)17490
ns/iter (± 145
)1.00
tuid/Tuid::random
34
ns/iter (± 0
)34
ns/iter (± 1
)1
This comment was automatically generated by workflow using github-action-benchmark.