ext/heap_profiler/heap_profiler.cpp in heap-profiler-0.2.1 vs ext/heap_profiler/heap_profiler.cpp in heap-profiler-0.3.0

- old
+ new

@@ -1,14 +1,15 @@ #include "ruby.h" +#include "ruby/encoding.h" #include "simdjson.h" #include <fstream> using namespace simdjson; static VALUE rb_eHeapProfilerError, sym_type, sym_class, sym_address, sym_value, sym_memsize, sym_imemo_type, sym_struct, sym_file, sym_line, sym_shared, - sym_references; + sym_references, id_uminus; typedef struct { dom::parser *parser; } parser_t; @@ -81,10 +82,28 @@ return 0; // ROOT object } return parse_address(address); } +static inline VALUE make_symbol(std::string_view string) { + return ID2SYM(rb_intern2(string.data(), string.size())); +} + +static inline VALUE make_string(std::string_view string) { + return rb_utf8_str_new(string.data(), string.size()); +} + +# ifdef HAVE_RB_ENC_INTERNED_STR + static inline VALUE dedup_string(std::string_view string) { + return rb_enc_interned_str(string.data(), string.size(), rb_utf8_encoding()); + } +# else + static inline VALUE dedup_string(std::string_view string) { + return rb_funcall(make_string(string), id_uminus, 0); + } +# endif + static VALUE rb_heap_build_index(VALUE self, VALUE path, VALUE batch_size) { Check_Type(path, T_STRING); Check_Type(batch_size, T_FIXNUM); dom::parser *parser = get_parser(self); @@ -105,18 +124,35 @@ if (type == "STRING") { std::string_view value; if (!object["value"].get(value)) { VALUE address = INT2FIX(parse_dom_address(object["address"])); - VALUE string = rb_utf8_str_new(value.data(), value.size()); + VALUE string = make_string(value); rb_hash_aset(string_index, address, string); } } else if (type == "CLASS" || type == "MODULE") { + VALUE address = INT2FIX(parse_dom_address(object["address"])); + VALUE class_name = Qfalse; + std::string_view name; if (!object["name"].get(name)) { - VALUE address = INT2FIX(parse_dom_address(object["address"])); - VALUE class_name = rb_utf8_str_new(name.data(), name.size()); + class_name = dedup_string(name); + } else { + std::string_view file; + uint64_t line; + + if (!object["file"].get(file) && !object["line"].get(line)) { + std::string buffer = "<Class "; + buffer += file; + buffer += ":"; + buffer += std::to_string(line); + buffer += ">"; + class_name = dedup_string(buffer); + } + } + + if (RTEST(class_name)) { rb_hash_aset(class_index, address, class_name); } } } } catch (simdjson::simdjson_error error) { @@ -138,11 +174,11 @@ { VALUE hash = rb_hash_new(); std::string_view type; if (!object["type"].get(type)) { - rb_hash_aset(hash, sym_type, ID2SYM(rb_intern2(type.data(), type.size()))); + rb_hash_aset(hash, sym_type, make_symbol(type)); } std::string_view address; if (!object["address"].get(address)) { rb_hash_aset(hash, sym_address, INT2FIX(parse_address(address))); @@ -162,21 +198,21 @@ } if (type == "IMEMO") { std::string_view imemo_type; if (!object["imemo_type"].get(imemo_type)) { - rb_hash_aset(hash, sym_imemo_type, ID2SYM(rb_intern2(imemo_type.data(), imemo_type.size()))); + rb_hash_aset(hash, sym_imemo_type, make_symbol(imemo_type)); } } else if (type == "DATA") { std::string_view _struct; if (!object["struct"].get(_struct)) { - rb_hash_aset(hash, sym_struct, ID2SYM(rb_intern2(_struct.data(), _struct.size()))); + rb_hash_aset(hash, sym_struct, make_symbol(_struct)); } } else if (type == "STRING") { std::string_view value; if (!object["value"].get(value)) { - rb_hash_aset(hash, sym_value, rb_utf8_str_new(value.data(), value.size())); + rb_hash_aset(hash, sym_value, make_string(value)); } bool shared; if (!object["shared"].get(shared)) { rb_hash_aset(hash, sym_shared, shared ? Qtrue : Qnil); @@ -194,11 +230,11 @@ } } std::string_view file; if (!object["file"].get(file)) { - rb_hash_aset(hash, sym_file, rb_utf8_str_new(file.data(), file.size())); + rb_hash_aset(hash, sym_file, dedup_string(file)); } uint64_t line; if (!object["line"].get(line)) { rb_hash_aset(hash, sym_line, INT2FIX(line)); @@ -259,9 +295,10 @@ sym_imemo_type = ID2SYM(rb_intern("imemo_type")); sym_file = ID2SYM(rb_intern("file")); sym_line = ID2SYM(rb_intern("line")); sym_shared = ID2SYM(rb_intern("shared")); sym_references = ID2SYM(rb_intern("references")); + id_uminus = rb_intern("-@"); VALUE rb_mHeapProfiler = rb_const_get(rb_cObject, rb_intern("HeapProfiler")); rb_eHeapProfilerError = rb_const_get(rb_mHeapProfiler, rb_intern("Error")); rb_global_variable(&rb_eHeapProfilerError);