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);