-
Notifications
You must be signed in to change notification settings - Fork 388
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Turn on allocation tracker at run-time and for web (#1591)
* Fix copy/paste in web viewer * Memory tracker callstack: shorten file paths * Fix typo * clean up copy-pasta comment * code refactor * allow turning on allocation tracking at runtime from the memory panel * nicer formatting in memory panel * Notice text layout allocations in the summaries * Notice failures to copy the backtrace * Notice empty backtraces * Fix stacktraces on web * wasm_bindgen_check: build to target_wasm * Always use target_wasm as build-dir when building wasm32 * Trim callstacks on web * typo fixe Co-authored-by: Andreas Reich <[email protected]> * Use a checkbox for the detailed allocation tracking * Make web callstack even nicer * Even nicer callstacks --------- Co-authored-by: Andreas Reich <[email protected]>
- Loading branch information
Showing
13 changed files
with
286 additions
and
88 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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
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,120 @@ | ||
use std::sync::Arc; | ||
|
||
pub(crate) struct Backtrace(backtrace::Backtrace); | ||
|
||
impl Backtrace { | ||
pub fn new_unresolved() -> Self { | ||
Self(backtrace::Backtrace::new_unresolved()) | ||
} | ||
|
||
pub fn format(&mut self) -> Arc<str> { | ||
self.0.resolve(); | ||
let stack = backtrace_to_string(&self.0); | ||
trim_backtrace(&stack).into() | ||
} | ||
} | ||
|
||
impl std::hash::Hash for Backtrace { | ||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) { | ||
for frame in self.0.frames() { | ||
frame.ip().hash(state); | ||
} | ||
} | ||
} | ||
|
||
fn trim_backtrace(mut stack: &str) -> &str { | ||
let start_pattern = "re_memory::accounting_allocator::note_alloc\n"; | ||
if let Some(start_offset) = stack.find(start_pattern) { | ||
stack = &stack[start_offset + start_pattern.len()..]; | ||
} | ||
|
||
let end_pattern = "std::sys_common::backtrace::__rust_begin_short_backtrace"; | ||
if let Some(end_offset) = stack.find(end_pattern) { | ||
stack = &stack[..end_offset]; | ||
} | ||
|
||
stack | ||
} | ||
|
||
fn backtrace_to_string(backtrace: &backtrace::Backtrace) -> String { | ||
if backtrace.frames().is_empty() { | ||
return "[empty backtrace]".to_owned(); | ||
} | ||
|
||
// We need to get a `std::fmt::Formatter`, and there is no easy way to do that, so we do it the hard way: | ||
|
||
struct AnonymizedBacktrace<'a>(&'a backtrace::Backtrace); | ||
|
||
impl<'a> std::fmt::Display for AnonymizedBacktrace<'a> { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
format_backtrace_with_fmt(self.0, f) | ||
} | ||
} | ||
|
||
AnonymizedBacktrace(backtrace).to_string() | ||
} | ||
|
||
fn format_backtrace_with_fmt( | ||
backtrace: &backtrace::Backtrace, | ||
fmt: &mut std::fmt::Formatter<'_>, | ||
) -> std::fmt::Result { | ||
let mut print_path = |fmt: &mut std::fmt::Formatter<'_>, | ||
path: backtrace::BytesOrWideString<'_>| { | ||
let path = path.into_path_buf(); | ||
let shortened = shorten_source_file_path(&path); | ||
std::fmt::Display::fmt(&shortened, fmt) | ||
}; | ||
|
||
let style = if fmt.alternate() { | ||
backtrace::PrintFmt::Full | ||
} else { | ||
backtrace::PrintFmt::Short | ||
}; | ||
let mut f = backtrace::BacktraceFmt::new(fmt, style, &mut print_path); | ||
f.add_context()?; | ||
for frame in backtrace.frames() { | ||
f.frame().backtrace_frame(frame)?; | ||
} | ||
f.finish()?; | ||
Ok(()) | ||
} | ||
|
||
/// Anonymize a path to a Rust source file from a callstack. | ||
/// | ||
/// Example input: | ||
/// * `/Users/emilk/.cargo/registry/src/jackfan.us.kg-1ecc6299db9ec823/tokio-1.24.1/src/runtime/runtime.rs` | ||
/// * `crates/rerun/src/main.rs` | ||
/// * `/rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/ops/function.rs` | ||
fn shorten_source_file_path(path: &std::path::Path) -> String { | ||
// We must make sure we strip everything sensitive (especially user name). | ||
// The easiest way is to look for `src` and strip everything up to it. | ||
|
||
use itertools::Itertools as _; | ||
let components = path.iter().map(|path| path.to_string_lossy()).collect_vec(); | ||
|
||
// Look for the last `src`: | ||
if let Some((src_rev_idx, _)) = components.iter().rev().find_position(|&c| c == "src") { | ||
let src_idx = components.len() - src_rev_idx - 1; | ||
// Before `src` comes the name of the crate - let's include that: | ||
let first_index = src_idx.saturating_sub(1); | ||
components.iter().skip(first_index).format("/").to_string() | ||
} else { | ||
// No `src` directory found - weird! | ||
path.display().to_string() | ||
} | ||
} | ||
|
||
#[test] | ||
fn test_shorten_path() { | ||
for (before, after) in [ | ||
("/Users/emilk/.cargo/registry/src/jackfan.us.kg-1ecc6299db9ec823/tokio-1.24.1/src/runtime/runtime.rs", "tokio-1.24.1/src/runtime/runtime.rs"), | ||
("crates/rerun/src/main.rs", "rerun/src/main.rs"), | ||
("/rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/core/src/ops/function.rs", "core/src/ops/function.rs"), | ||
("/weird/path/file.rs", "/weird/path/file.rs"), | ||
] | ||
{ | ||
use std::str::FromStr as _; | ||
let before = std::path::PathBuf::from_str(before).unwrap(); | ||
assert_eq!(shorten_source_file_path(&before), after); | ||
} | ||
} |
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,63 @@ | ||
use wasm_bindgen::prelude::*; | ||
|
||
#[wasm_bindgen] | ||
extern "C" { | ||
#[wasm_bindgen(js_namespace = console)] | ||
fn error(msg: String); | ||
|
||
type Error; | ||
|
||
#[wasm_bindgen(constructor)] | ||
fn new() -> Error; | ||
|
||
#[wasm_bindgen(structural, method, getter)] | ||
fn stack(error: &Error) -> String; | ||
} | ||
|
||
#[derive(Hash)] | ||
pub(crate) struct Backtrace(String); | ||
|
||
impl Backtrace { | ||
pub fn new_unresolved() -> Self { | ||
Self(Error::new().stack()) | ||
} | ||
|
||
pub fn format(&mut self) -> std::sync::Arc<str> { | ||
trim_backtrace(&self.0).into() | ||
} | ||
} | ||
|
||
fn trim_backtrace(mut stack: &str) -> String { | ||
let start_pattern = "__rust_alloc_zeroed"; | ||
if let Some(start_offset) = stack.find(start_pattern) { | ||
if let Some(next_newline) = stack[start_offset..].find('\n') { | ||
stack = &stack[start_offset + next_newline + 1..]; | ||
} | ||
} | ||
|
||
let end_pattern = "paint_and_schedule"; // normal eframe entry-point | ||
if let Some(end_offset) = stack.find(end_pattern) { | ||
if let Some(next_newline) = stack[end_offset..].find('\n') { | ||
stack = &stack[..end_offset + next_newline]; | ||
} | ||
} | ||
|
||
stack.split('\n').map(trim_line).collect::<String>() | ||
} | ||
|
||
/// Example inputs: | ||
/// * `eframe::web::backend::AppRunner::paint::h584aff3234354fd5@http://127.0.0.1:9090/re_viewer.js line 366 > WebAssembly.instantiate:wasm-function[3352]:0x5d46b4` | ||
/// * `getImports/imports.wbg.__wbg_new_83e4891414f9e5c1/<@http://127.0.0.1:9090/re_viewer.js:453:21` | ||
/// * `__rg_realloc@http://127.0.0.1:9090/re_viewer.js line 366 > WebAssembly.instantiate:wasm-function[17996]:0x9b935f` | ||
fn trim_line(mut line: &str) -> String { | ||
if let Some(index) = line.rfind("::") { | ||
line = &line[..index]; | ||
} | ||
if let Some(index) = line.find("/imports.wbg") { | ||
line = &line[..index]; | ||
} | ||
if let Some(index) = line.find("@http:") { | ||
line = &line[..index]; | ||
} | ||
format!("{line}\n") | ||
} |
Oops, something went wrong.
364f86d
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
565626
ns/iter (± 2791
)559261
ns/iter (± 1861
)1.01
datastore/latest_at/batch/rects/query
1815
ns/iter (± 5
)1840
ns/iter (± 30
)0.99
datastore/latest_at/missing_components/primary
285
ns/iter (± 0
)286
ns/iter (± 0
)1.00
datastore/latest_at/missing_components/secondaries
438
ns/iter (± 2
)438
ns/iter (± 0
)1
datastore/range/batch/rects/query
152385
ns/iter (± 222
)151520
ns/iter (± 519
)1.01
mono_points_arrow/generate_message_bundles
53571375
ns/iter (± 1058657
)48318016
ns/iter (± 494422
)1.11
mono_points_arrow/generate_messages
141821941
ns/iter (± 1654501
)127474339
ns/iter (± 1508294
)1.11
mono_points_arrow/encode_log_msg
168643961
ns/iter (± 2034860
)159549179
ns/iter (± 1325016
)1.06
mono_points_arrow/encode_total
373382705
ns/iter (± 4015002
)337112136
ns/iter (± 1931763
)1.11
mono_points_arrow/decode_log_msg
191288531
ns/iter (± 7707687
)181004618
ns/iter (± 744958
)1.06
mono_points_arrow/decode_message_bundles
76612590
ns/iter (± 1439086
)65470475
ns/iter (± 794309
)1.17
mono_points_arrow/decode_total
265899147
ns/iter (± 2557182
)243039709
ns/iter (± 1379454
)1.09
batch_points_arrow/generate_message_bundles
326287
ns/iter (± 3260
)323386
ns/iter (± 480
)1.01
batch_points_arrow/generate_messages
6502
ns/iter (± 26
)6458
ns/iter (± 20
)1.01
batch_points_arrow/encode_log_msg
362765
ns/iter (± 2535
)356799
ns/iter (± 984
)1.02
batch_points_arrow/encode_total
712671
ns/iter (± 6012
)706689
ns/iter (± 2127
)1.01
batch_points_arrow/decode_log_msg
341372
ns/iter (± 2111
)347642
ns/iter (± 1114
)0.98
batch_points_arrow/decode_message_bundles
2090
ns/iter (± 20
)2072
ns/iter (± 12
)1.01
batch_points_arrow/decode_total
367811
ns/iter (± 21060
)356898
ns/iter (± 1454
)1.03
arrow_mono_points/insert
9256181423
ns/iter (± 120643625
)6126182762
ns/iter (± 35168800
)1.51
arrow_mono_points/query
1847569
ns/iter (± 39588
)1823165
ns/iter (± 16496
)1.01
arrow_batch_points/insert
2862042
ns/iter (± 314987
)2768566
ns/iter (± 73357
)1.03
arrow_batch_points/query
16966
ns/iter (± 70
)17005
ns/iter (± 39
)1.00
arrow_batch_vecs/insert
42618
ns/iter (± 150
)42357
ns/iter (± 101
)1.01
arrow_batch_vecs/query
506559
ns/iter (± 1221
)507025
ns/iter (± 1072
)1.00
tuid/Tuid::random
34
ns/iter (± 0
)34
ns/iter (± 0
)1
This comment was automatically generated by workflow using github-action-benchmark.
364f86d
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.
Possible performance regression was detected for benchmark 'Rust Benchmark'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold
1.50
.arrow_mono_points/insert
9256181423
ns/iter (± 120643625
)6126182762
ns/iter (± 35168800
)1.51
This comment was automatically generated by workflow using github-action-benchmark.