Skip to content

Commit 1883264

Browse files
committed
Generate benchmark scenario
1 parent d72dcab commit 1883264

File tree

3 files changed

+176
-8
lines changed

3 files changed

+176
-8
lines changed

datadog-crashtracker/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ receiver = []
3232
collector_windows = []
3333
generate-unit-test-files = []
3434
# Enables benchmark functionality
35-
benchmarking = []
35+
benchmarking = ["generate-unit-test-files"]
3636

3737
[target.'cfg(unix)'.dependencies]
3838
# Should be kept in sync with the libdatadog symbolizer crate (also using blasesym)

datadog-crashtracker/benches/receiver_bench.rs

Lines changed: 174 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,163 @@
33

44
use criterion::{black_box, criterion_group, BenchmarkId, Criterion};
55
use datadog_crashtracker::benchmark::receiver_entry_point;
6+
use libc::c_void;
7+
use std::ffi::CString;
8+
use std::fmt::Write;
9+
use std::path::Path;
10+
use std::path::PathBuf;
611
use std::time::Duration;
712
use tokio::io::BufReader;
813

9-
fn create_dummy_crash_report() -> String {
10-
r#"DD_CRASHTRACK_BEGIN_STACKTRACE
11-
{ "ip": "0x42", "module_address": "0x21", "sp": "0x11", "symbol_address": "0x73" }
12-
DD_CRASHTRACK_END_STACKTRACE
13-
DD_CRASHTRACK_DONE"#
14-
.to_string()
14+
struct SharedLibrary {
15+
handle: *mut c_void,
16+
}
17+
18+
impl SharedLibrary {
19+
fn open(lib_path: &str) -> Result<Self, String> {
20+
let cstr = CString::new(lib_path).map_err(|e| e.to_string())?;
21+
// Use RTLD_NOW or another flag
22+
let handle = unsafe { libc::dlopen(cstr.as_ptr(), libc::RTLD_NOW) };
23+
if handle.is_null() {
24+
Err("Failed to open library".to_string())
25+
} else {
26+
Ok(Self { handle })
27+
}
28+
}
29+
30+
fn get_symbol_address(&self, symbol: &str) -> Result<String, String> {
31+
let cstr = CString::new(symbol).map_err(|e| e.to_string())?;
32+
let sym = unsafe { libc::dlsym(self.handle, cstr.as_ptr()) };
33+
if sym.is_null() {
34+
Err(format!("Failed to find symbol: {}", symbol))
35+
} else {
36+
Ok(format!("{:p}", sym))
37+
}
38+
}
39+
}
40+
41+
impl Drop for SharedLibrary {
42+
fn drop(&mut self) {
43+
if !self.handle.is_null() {
44+
unsafe { libc::dlclose(self.handle) };
45+
}
46+
}
47+
}
48+
49+
fn get_data_folder_path() -> PathBuf {
50+
Path::new(&env!("CARGO_MANIFEST_DIR"))
51+
.join("data")
52+
.canonicalize()
53+
.expect("Failed to canonicalize base path for libtest")
54+
}
55+
56+
macro_rules! add_frame {
57+
($report:expr, $fn:expr, $lib:expr) => {
58+
add_frame!($report, $lib.get_symbol_address($fn).unwrap().as_str());
59+
};
60+
($report:expr, $address:expr) => {
61+
writeln!(
62+
$report,
63+
"{{ \"ip\": \"{}\", \"module_address\": \"0x21\", \"sp\": \"0x11\" }}",
64+
$address
65+
)
66+
.expect("Failed to write frame");
67+
};
68+
}
69+
70+
fn add_proc_info(report: &mut String) {
71+
report.push_str("DD_CRASHTRACK_BEGIN_PROCESSINFO\n");
72+
writeln!(report, "{{ \"pid\": {} }}", std::process::id()).expect("Failed to write PID");
73+
report.push_str("DD_CRASHTRACK_END_PROCESSINFO\n");
74+
}
75+
76+
fn add_config(report: &mut String) {
77+
report.push_str("DD_CRASHTRACK_BEGIN_CONFIG\n");
78+
report.push_str("{\"additional_files\":[],\"create_alt_stack\":true,\"demangle_names\":true,\"endpoint\":null,\"resolve_frames\":\"EnabledWithSymbolsInReceiver\",\"signals\":[4,6,7,11],\"timeout\":{\"secs\":10,\"nanos\":0},\"unix_socket_path\":\"\",\"use_alt_stack\":true}\n");
79+
report.push_str("DD_CRASHTRACK_END_CONFIG\n");
80+
}
81+
82+
fn add_stacktrace(report: &mut String, test_cpp_so: &SharedLibrary, test_c_so: &SharedLibrary) {
83+
report.push_str("DD_CRASHTRACK_BEGIN_STACKTRACE\n");
84+
85+
add_frame!(report, "my_function", test_c_so);
86+
add_frame!(report, "func1", test_c_so);
87+
add_frame!(report, "func2", test_c_so);
88+
add_frame!(report, "0x01");
89+
add_frame!(report, "0x02");
90+
add_frame!(report, "_Z12cpp_functionv", test_cpp_so);
91+
add_frame!(
92+
report,
93+
"_ZN10FirstClass10InnerClass12InnerMethod1Ev",
94+
test_cpp_so
95+
);
96+
add_frame!(
97+
report,
98+
"_ZN10FirstClass10InnerClass12InnerMethod2Ev",
99+
test_cpp_so
100+
);
101+
add_frame!(report, "0x03");
102+
add_frame!(report, "0x03");
103+
add_frame!(report, "0x05");
104+
add_frame!(report, "func3", test_c_so);
105+
add_frame!(report, "_ZN10FirstClass7Method1Ev", test_cpp_so);
106+
add_frame!(report, "func4", test_c_so);
107+
add_frame!(
108+
report,
109+
"_ZN10FirstClass7Method2EibNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE",
110+
test_cpp_so
111+
);
112+
add_frame!(report, "0x06");
113+
add_frame!(report, "func5", test_c_so);
114+
add_frame!(report, "func6", test_c_so);
115+
add_frame!(
116+
report,
117+
"_ZN11MyNamespace16ClassInNamespace18MethodInNamespace1Efx",
118+
test_cpp_so
119+
);
120+
add_frame!(report, "0x07");
121+
add_frame!(
122+
report,
123+
"_ZN11MyNamespace16ClassInNamespace18MethodInNamespace2Edc",
124+
test_cpp_so
125+
);
126+
add_frame!(report, "0x08");
127+
add_frame!(report, "func6", test_c_so);
128+
add_frame!(report, "0x09");
129+
add_frame!(
130+
report,
131+
"_ZN11MyNamespace16ClassInNamespace21InnerClassInNamespace12InnerMethod1Ev",
132+
test_cpp_so
133+
);
134+
add_frame!(report, "0x0A");
135+
add_frame!(
136+
report,
137+
"_ZN11MyNamespace16ClassInNamespace21InnerClassInNamespace12InnerMethod2Eiix",
138+
test_cpp_so
139+
);
140+
add_frame!(report, "0x0B");
141+
add_frame!(report, "func7", test_c_so);
142+
add_frame!(report, "func8", test_c_so);
143+
add_frame!(
144+
report,
145+
"_ZN11MyNamespace16ClassInNamespace21InnerClassInNamespace12InnerMethod2Eiix",
146+
test_cpp_so
147+
);
148+
add_frame!(report, "func9", test_c_so);
149+
add_frame!(report, "func10", test_c_so);
150+
add_frame!(report, "0x00");
151+
152+
report.push_str("DD_CRASHTRACK_END_STACKTRACE\n");
153+
}
154+
155+
fn create_crash_report(test_cpp_so: &SharedLibrary, test_c_so: &SharedLibrary) -> String {
156+
// Manual test revealed that the report size was arount 3000 bytes
157+
let mut report = String::with_capacity(3000);
158+
add_proc_info(&mut report);
159+
add_config(&mut report);
160+
add_stacktrace(&mut report, test_cpp_so, test_c_so);
161+
report.push_str("DD_CRASHTRACK_DONE\n");
162+
report
15163
}
16164

17165
async fn bench_receiver_entry_point_from_str(data: &str) {
@@ -22,10 +170,29 @@ async fn bench_receiver_entry_point_from_str(data: &str) {
22170
let _ = receiver_entry_point(timeout, reader).await;
23171
}
24172

173+
fn load_test_libraries() -> (SharedLibrary, SharedLibrary) {
174+
let sofile_c_path = get_data_folder_path()
175+
.join("libtest.so")
176+
.canonicalize()
177+
.unwrap();
178+
179+
let sofile_cpp_path = get_data_folder_path()
180+
.join("libtest_cpp.so")
181+
.canonicalize()
182+
.unwrap();
183+
184+
let test_c_so = SharedLibrary::open(sofile_c_path.to_str().unwrap()).unwrap();
185+
let test_cpp_so = SharedLibrary::open(sofile_cpp_path.to_str().unwrap()).unwrap();
186+
(test_cpp_so, test_c_so)
187+
}
188+
25189
pub fn receiver_entry_point_benchmarks(c: &mut Criterion) {
26190
let mut group = c.benchmark_group("receiver_entry_point");
27191

28-
let report = create_dummy_crash_report();
192+
// the libraries must be opened as long as the benchmark is running
193+
// That why we pass them as references
194+
let (sofile_cpp, sofile_c) = load_test_libraries();
195+
let report = create_crash_report(&sofile_cpp, &sofile_c);
29196
group.bench_with_input(
30197
BenchmarkId::new("report", report.len()),
31198
&report,

datadog-crashtracker/src/receiver/entry_points.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ pub(crate) async fn receiver_entry_point(
111111
.push(format!("Error demangling names: {e}"));
112112
}
113113
}
114+
//println!("---- upload crash info {:?}", crash_info);
114115
crash_info
115116
.async_upload_to_endpoint(config.endpoint())
116117
.await?;

0 commit comments

Comments
 (0)