Skip to content

Commit 8ffe445

Browse files
committed
feat(native): cache rb_intern ids
1 parent 66c454d commit 8ffe445

File tree

1 file changed

+47
-33
lines changed
  • gems/native-tracer/ext/native_tracer/src

1 file changed

+47
-33
lines changed

gems/native-tracer/ext/native_tracer/src/lib.rs

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ extern "C" {
6363
struct Recorder {
6464
tracer: Tracer,
6565
active: bool,
66+
to_s_id: ID,
67+
locals_id: ID,
68+
local_get_id: ID,
69+
inst_meth_id: ID,
70+
parameters_id: ID,
71+
class_id: ID,
6672
}
6773

6874
unsafe extern "C" fn recorder_free(ptr: *mut c_void) {
@@ -101,7 +107,22 @@ unsafe extern "C" fn ruby_recorder_alloc(klass: VALUE) -> VALUE {
101107
let path = Path::new("");
102108
let func_id = tracer.ensure_function_id("<top-level>", path, Line(1));
103109
tracer.events.push(TraceLowLevelEvent::Call(CallRecord { function_id: func_id, args: vec![] }));
104-
let recorder = Box::new(Recorder { tracer, active: false });
110+
let to_s_id = rb_intern(b"to_s\0".as_ptr() as *const c_char);
111+
let locals_id = rb_intern(b"local_variables\0".as_ptr() as *const c_char);
112+
let local_get_id = rb_intern(b"local_variable_get\0".as_ptr() as *const c_char);
113+
let inst_meth_id = rb_intern(b"instance_method\0".as_ptr() as *const c_char);
114+
let parameters_id = rb_intern(b"parameters\0".as_ptr() as *const c_char);
115+
let class_id = rb_intern(b"class\0".as_ptr() as *const c_char);
116+
let recorder = Box::new(Recorder {
117+
tracer,
118+
active: false,
119+
to_s_id,
120+
locals_id,
121+
local_get_id,
122+
inst_meth_id,
123+
parameters_id,
124+
class_id,
125+
});
105126
let ty = std::ptr::addr_of!(RECORDER_TYPE) as *const rb_data_type_t;
106127
rb_data_typed_object_wrap(klass, Box::into_raw(recorder) as *mut c_void, ty)
107128
}
@@ -151,22 +172,21 @@ unsafe fn cstr_to_string(ptr: *const c_char) -> Option<String> {
151172
CStr::from_ptr(ptr).to_str().ok().map(|s| s.to_string())
152173
}
153174

154-
unsafe fn value_to_string(val: VALUE) -> Option<String> {
175+
unsafe fn value_to_string(val: VALUE, to_s_id: ID) -> Option<String> {
155176
if RB_TYPE_P(val, rb_sys::ruby_value_type::RUBY_T_STRING) {
156177
let ptr = RSTRING_PTR(val);
157178
let len = RSTRING_LEN(val) as usize;
158179
let slice = std::slice::from_raw_parts(ptr as *const u8, len);
159180
return Some(String::from_utf8_lossy(slice).to_string());
160181
}
161-
let to_s_id = rb_intern(b"to_s\0".as_ptr() as *const c_char);
162182
let str_val = rb_funcall(val, to_s_id, 0);
163183
let ptr = RSTRING_PTR(str_val);
164184
let len = RSTRING_LEN(str_val) as usize;
165185
let slice = std::slice::from_raw_parts(ptr as *const u8, len);
166186
Some(String::from_utf8_lossy(slice).to_string())
167187
}
168188

169-
unsafe fn to_value(tracer: &mut Tracer, val: VALUE, depth: usize) -> ValueRecord {
189+
unsafe fn to_value(tracer: &mut Tracer, val: VALUE, depth: usize, to_s_id: ID) -> ValueRecord {
170190
if depth == 0 {
171191
let type_id = tracer.ensure_type_id(TypeKind::Error, "No type");
172192
return ValueRecord::None { type_id };
@@ -203,45 +223,40 @@ unsafe fn to_value(tracer: &mut Tracer, val: VALUE, depth: usize) -> ValueRecord
203223
let ptr = RARRAY_CONST_PTR(val);
204224
for i in 0..len {
205225
let elem = *ptr.add(i);
206-
elements.push(to_value(tracer, elem, depth - 1));
226+
elements.push(to_value(tracer, elem, depth - 1, to_s_id));
207227
}
208228
let type_id = tracer.ensure_type_id(TypeKind::Seq, "Array");
209229
return ValueRecord::Sequence { elements, is_slice: false, type_id };
210230
}
211231
let class_name = cstr_to_string(rb_obj_classname(val)).unwrap_or_else(|| "Object".to_string());
212-
let text = value_to_string(val).unwrap_or_default();
232+
let text = value_to_string(val, to_s_id).unwrap_or_default();
213233
let type_id = tracer.ensure_type_id(TypeKind::Raw, &class_name);
214234
ValueRecord::Raw { r: text, type_id }
215235
}
216236

217-
unsafe fn record_variables(tracer: &mut Tracer, binding: VALUE) -> Vec<FullValueRecord> {
237+
unsafe fn record_variables(recorder: &mut Recorder, binding: VALUE) -> Vec<FullValueRecord> {
218238
let mut result = Vec::new();
219-
let locals_id = rb_intern(b"local_variables\0".as_ptr() as *const c_char);
220-
let get_id = rb_intern(b"local_variable_get\0".as_ptr() as *const c_char);
221-
let vars = rb_funcall(binding, locals_id, 0);
239+
let vars = rb_funcall(binding, recorder.locals_id, 0);
222240
let len = RARRAY_LEN(vars) as usize;
223241
let ptr = RARRAY_CONST_PTR(vars);
224242
for i in 0..len {
225243
let sym = *ptr.add(i);
226244
let id = rb_sym2id(sym);
227245
let name = CStr::from_ptr(rb_id2name(id)).to_str().unwrap_or("");
228-
let value = rb_funcall(binding, get_id, 1, sym);
229-
let val_rec = to_value(tracer, value, 10);
230-
tracer.register_variable_with_full_value(name, val_rec.clone());
231-
let var_id = tracer.ensure_variable_id(name);
246+
let value = rb_funcall(binding, recorder.local_get_id, 1, sym);
247+
let val_rec = to_value(&mut recorder.tracer, value, 10, recorder.to_s_id);
248+
recorder.tracer.register_variable_with_full_value(name, val_rec.clone());
249+
let var_id = recorder.tracer.ensure_variable_id(name);
232250
result.push(FullValueRecord { variable_id: var_id, value: val_rec });
233251
}
234252
result
235253
}
236254

237-
unsafe fn record_parameters(tracer: &mut Tracer, binding: VALUE, defined_class: VALUE, mid: ID, register: bool) -> Vec<FullValueRecord> {
255+
unsafe fn record_parameters(recorder: &mut Recorder, binding: VALUE, defined_class: VALUE, mid: ID, register: bool) -> Vec<FullValueRecord> {
238256
let mut result = Vec::new();
239-
let inst_meth_id = rb_intern(b"instance_method\0".as_ptr() as *const c_char);
240-
let parameters_id = rb_intern(b"parameters\0".as_ptr() as *const c_char);
241-
let local_get_id = rb_intern(b"local_variable_get\0".as_ptr() as *const c_char);
242257
let method_sym = rb_id2sym(mid);
243-
let method_obj = rb_funcall(defined_class, inst_meth_id, 1, method_sym);
244-
let params_ary = rb_funcall(method_obj, parameters_id, 0);
258+
let method_obj = rb_funcall(defined_class, recorder.inst_meth_id, 1, method_sym);
259+
let params_ary = rb_funcall(method_obj, recorder.parameters_id, 0);
245260
let params_len = RARRAY_LEN(params_ary) as usize;
246261
let params_ptr = RARRAY_CONST_PTR(params_ary);
247262
for i in 0..params_len {
@@ -260,11 +275,11 @@ unsafe fn record_parameters(tracer: &mut Tracer, binding: VALUE, defined_class:
260275
continue;
261276
}
262277
let name = CStr::from_ptr(name_c).to_str().unwrap_or("");
263-
let value = rb_funcall(binding, local_get_id, 1, name_sym);
264-
let val_rec = to_value(tracer, value, 10);
278+
let value = rb_funcall(binding, recorder.local_get_id, 1, name_sym);
279+
let val_rec = to_value(&mut recorder.tracer, value, 10, recorder.to_s_id);
265280
if register {
266-
tracer.register_variable_with_full_value(name, val_rec.clone());
267-
let var_id = tracer.ensure_variable_id(name);
281+
recorder.tracer.register_variable_with_full_value(name, val_rec.clone());
282+
let var_id = recorder.tracer.ensure_variable_id(name);
268283
result.push(FullValueRecord { variable_id: var_id, value: val_rec });
269284
}
270285
}
@@ -309,7 +324,7 @@ unsafe extern "C" fn record_event_api(self_val: VALUE, path: VALUE, line: VALUE,
309324
String::from_utf8_lossy(std::slice::from_raw_parts(ptr as *const u8, len)).to_string()
310325
};
311326
let line_num = rb_num2long(line) as i64;
312-
let content_str = value_to_string(content).unwrap_or_default();
327+
let content_str = value_to_string(content, recorder.to_s_id).unwrap_or_default();
313328
record_event(&mut recorder.tracer, &path_str, line_num, &content_str);
314329
rb_sys::Qnil.into()
315330
}
@@ -350,29 +365,28 @@ unsafe extern "C" fn event_hook_raw(data: VALUE, arg: *mut rb_trace_arg_t) {
350365
let binding = rb_tracearg_binding(arg);
351366
recorder.tracer.register_step(Path::new(&path), Line(line));
352367
if !NIL_P(binding) {
353-
record_variables(&mut recorder.tracer, binding);
368+
record_variables(recorder, binding);
354369
}
355370
} else if (ev & RUBY_EVENT_CALL) != 0 {
356371
let binding = rb_tracearg_binding(arg);
357372

358373
let self_val = rb_tracearg_self(arg);
359374
let mid_sym = rb_tracearg_callee_id(arg);
360375
let mid = rb_sym2id(mid_sym);
361-
let class_id = rb_intern(b"class\0".as_ptr() as *const c_char);
362-
let defined_class = rb_funcall(self_val, class_id, 0);
376+
let defined_class = rb_funcall(self_val, recorder.class_id, 0);
363377
if !NIL_P(binding) {
364378
// register parameter types first
365-
let _ = record_parameters(&mut recorder.tracer, binding, defined_class, mid, false);
379+
let _ = record_parameters(recorder, binding, defined_class, mid, false);
366380
}
367-
let self_rec = to_value(&mut recorder.tracer, self_val, 10);
381+
let self_rec = to_value(&mut recorder.tracer, self_val, 10, recorder.to_s_id);
368382
recorder
369383
.tracer
370384
.register_variable_with_full_value("self", self_rec.clone());
371385

372386
let mut args = if NIL_P(binding) {
373387
vec![]
374388
} else {
375-
record_parameters(&mut recorder.tracer, binding, defined_class, mid, true)
389+
record_parameters(recorder, binding, defined_class, mid, true)
376390
};
377391
args.insert(0, recorder.tracer.arg("self", self_rec));
378392
recorder.tracer.register_step(Path::new(&path), Line(line));
@@ -391,12 +405,12 @@ unsafe extern "C" fn event_hook_raw(data: VALUE, arg: *mut rb_trace_arg_t) {
391405
} else if (ev & RUBY_EVENT_RETURN) != 0 {
392406
recorder.tracer.register_step(Path::new(&path), Line(line));
393407
let ret = rb_tracearg_return_value(arg);
394-
let val_rec = to_value(&mut recorder.tracer, ret, 10);
408+
let val_rec = to_value(&mut recorder.tracer, ret, 10, recorder.to_s_id);
395409
recorder.tracer.register_variable_with_full_value("<return_value>", val_rec.clone());
396410
recorder.tracer.events.push(TraceLowLevelEvent::Return(ReturnRecord { return_value: val_rec }));
397411
} else if (ev & RUBY_EVENT_RAISE) != 0 {
398412
let exc = rb_tracearg_raised_exception(arg);
399-
if let Some(msg) = value_to_string(exc) {
413+
if let Some(msg) = value_to_string(exc, recorder.to_s_id) {
400414
recorder.tracer.events.push(TraceLowLevelEvent::Event(RecordEvent {
401415
kind: EventLogKind::Error,
402416
metadata: String::new(),

0 commit comments

Comments
 (0)