Skip to content

Commit 18c9c7c

Browse files
committed
chore(tracer): optimize event handling
Use pre-allocated vectors, avoid path string allocations, and enable LTO with native CPU flags for faster builds.
1 parent 45ec725 commit 18c9c7c

File tree

4 files changed

+32
-26
lines changed

4 files changed

+32
-26
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Read the native tracer code line by line, improve performance if possible, ensuring extension compiled with best optimization flags. Review build recipes.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[build]
2+
rustflags = ["-C", "target-cpu=native"]

gems/codetracer-ruby-recorder/ext/native_tracer/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,8 @@ runtime_tracing = "0.12.1"
1515

1616
[build-dependencies]
1717
rb-sys-env = "0.2"
18+
19+
[profile.release]
20+
codegen-units = 1
21+
lto = "thin"
22+
opt-level = 3

gems/codetracer-ruby-recorder/ext/native_tracer/src/lib.rs

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,9 @@ unsafe fn struct_value(
9797
depth: usize,
9898
to_s_id: ID,
9999
) -> ValueRecord {
100-
let mut vals = Vec::new();
101-
for v in field_values {
102-
vals.push(to_value(recorder, *v, depth - 1, to_s_id));
100+
let mut vals = Vec::with_capacity(field_values.len());
101+
for &v in field_values {
102+
vals.push(to_value(recorder, v, depth - 1, to_s_id));
103103
}
104104

105105
let version_entry = recorder
@@ -108,14 +108,13 @@ unsafe fn struct_value(
108108
.or_insert(0);
109109
let name_version = format!("{} (#{})", class_name, *version_entry);
110110
*version_entry += 1;
111-
let field_types: Vec<FieldTypeRecord> = field_names
112-
.iter()
113-
.zip(&vals)
114-
.map(|(n, v)| FieldTypeRecord {
111+
let mut field_types = Vec::with_capacity(field_names.len());
112+
for (n, v) in field_names.iter().zip(&vals) {
113+
field_types.push(FieldTypeRecord {
115114
name: (*n).to_string(),
116115
type_id: value_type_id(v),
117-
})
118-
.collect();
116+
});
117+
}
119118
let typ = TypeRecord {
120119
kind: TypeKind::Struct,
121120
lang_type: name_version,
@@ -365,7 +364,7 @@ unsafe fn to_value(recorder: &mut Recorder, val: VALUE, depth: usize, to_s_id: I
365364
}
366365
if RB_TYPE_P(val, rb_sys::ruby_value_type::RUBY_T_ARRAY) {
367366
let len = RARRAY_LEN(val) as usize;
368-
let mut elements = Vec::new();
367+
let mut elements = Vec::with_capacity(len);
369368
let ptr = RARRAY_CONST_PTR(val);
370369
for i in 0..len {
371370
let elem = *ptr.add(i);
@@ -382,7 +381,7 @@ unsafe fn to_value(recorder: &mut Recorder, val: VALUE, depth: usize, to_s_id: I
382381
let pairs = rb_funcall(val, recorder.to_a_id, 0);
383382
let len = RARRAY_LEN(pairs) as usize;
384383
let ptr = RARRAY_CONST_PTR(pairs);
385-
let mut elements = Vec::new();
384+
let mut elements = Vec::with_capacity(len);
386385
for i in 0..len {
387386
let pair = *ptr.add(i);
388387
if !RB_TYPE_P(pair, rb_sys::ruby_value_type::RUBY_T_ARRAY) || RARRAY_LEN(pair) < 2 {
@@ -429,7 +428,7 @@ unsafe fn to_value(recorder: &mut Recorder, val: VALUE, depth: usize, to_s_id: I
429428
if RB_TYPE_P(arr, rb_sys::ruby_value_type::RUBY_T_ARRAY) {
430429
let len = RARRAY_LEN(arr) as usize;
431430
let ptr = RARRAY_CONST_PTR(arr);
432-
let mut elements = Vec::new();
431+
let mut elements = Vec::with_capacity(len);
433432
for i in 0..len {
434433
let elem = *ptr.add(i);
435434
elements.push(to_value(recorder, elem, depth - 1, to_s_id));
@@ -481,8 +480,8 @@ unsafe fn to_value(recorder: &mut Recorder, val: VALUE, depth: usize, to_s_id: I
481480
let len = RARRAY_LEN(values) as usize;
482481
let mem_ptr = RARRAY_CONST_PTR(members);
483482
let val_ptr = RARRAY_CONST_PTR(values);
484-
let mut names: Vec<&str> = Vec::new();
485-
let mut vals: Vec<VALUE> = Vec::new();
483+
let mut names: Vec<&str> = Vec::with_capacity(len);
484+
let mut vals: Vec<VALUE> = Vec::with_capacity(len);
486485
for i in 0..len {
487486
let sym = *mem_ptr.add(i);
488487
let id = rb_sym2id(sym);
@@ -512,8 +511,8 @@ unsafe fn to_value(recorder: &mut Recorder, val: VALUE, depth: usize, to_s_id: I
512511
}
513512
let len = RARRAY_LEN(ivars) as usize;
514513
let ptr = RARRAY_CONST_PTR(ivars);
515-
let mut names: Vec<&str> = Vec::new();
516-
let mut vals: Vec<VALUE> = Vec::new();
514+
let mut names: Vec<&str> = Vec::with_capacity(len);
515+
let mut vals: Vec<VALUE> = Vec::with_capacity(len);
517516
for i in 0..len {
518517
let sym = *ptr.add(i);
519518
let id = rb_sym2id(sym);
@@ -532,12 +531,12 @@ unsafe fn to_value(recorder: &mut Recorder, val: VALUE, depth: usize, to_s_id: I
532531
}
533532

534533
unsafe fn record_variables(recorder: &mut Recorder, binding: VALUE) -> Vec<FullValueRecord> {
535-
let mut result = Vec::new();
536534
let vars = rb_funcall(binding, recorder.locals_id, 0);
537535
if !RB_TYPE_P(vars, rb_sys::ruby_value_type::RUBY_T_ARRAY) {
538-
return result;
536+
return Vec::new();
539537
}
540538
let len = RARRAY_LEN(vars) as usize;
539+
let mut result = Vec::with_capacity(len);
541540
let ptr = RARRAY_CONST_PTR(vars);
542541
for i in 0..len {
543542
let sym = *ptr.add(i);
@@ -564,18 +563,18 @@ unsafe fn record_parameters(
564563
mid: ID,
565564
register: bool,
566565
) -> Vec<FullValueRecord> {
567-
let mut result = Vec::new();
568566
let method_sym = rb_id2sym(mid);
569567
if rb_method_boundp(defined_class, mid, 0) == 0 {
570-
return result;
568+
return Vec::new();
571569
}
572570
let method_obj = rb_funcall(defined_class, recorder.inst_meth_id, 1, method_sym);
573571
let params_ary = rb_funcall(method_obj, recorder.parameters_id, 0);
574572
if !RB_TYPE_P(params_ary, rb_sys::ruby_value_type::RUBY_T_ARRAY) {
575-
return result;
573+
return Vec::new();
576574
}
577575
let params_len = RARRAY_LEN(params_ary) as usize;
578576
let params_ptr = RARRAY_CONST_PTR(params_ary);
577+
let mut result = Vec::with_capacity(params_len);
579578
for i in 0..params_len {
580579
let pair = *params_ptr.add(i);
581580
if !RB_TYPE_P(pair, rb_sys::ruby_value_type::RUBY_T_ARRAY) || RARRAY_LEN(pair) < 2 {
@@ -700,13 +699,12 @@ unsafe extern "C" fn event_hook_raw(data: VALUE, arg: *mut rb_trace_arg_t) {
700699
let ev: rb_event_flag_t = rb_tracearg_event_flag(arg);
701700
let path_val = rb_tracearg_path(arg);
702701
let line_val = rb_tracearg_lineno(arg);
703-
let path = if NIL_P(path_val) {
704-
"".to_string()
702+
let path_bytes = if NIL_P(path_val) {
703+
&[] as &[u8]
705704
} else {
706-
let ptr = RSTRING_PTR(path_val);
707-
let len = RSTRING_LEN(path_val) as usize;
708-
String::from_utf8_lossy(std::slice::from_raw_parts(ptr as *const u8, len)).to_string()
705+
std::slice::from_raw_parts(RSTRING_PTR(path_val) as *const u8, RSTRING_LEN(path_val) as usize)
709706
};
707+
let path = std::str::from_utf8(path_bytes).unwrap_or("");
710708
let line = rb_num2long(line_val) as i64;
711709
if path.contains("codetracer_ruby_recorder.rb")
712710
|| path.contains("lib/ruby")

0 commit comments

Comments
 (0)