Project

General

Profile

Feature #8158 » 0001-load.c-reduce-memory-usage-of-loaded_features_index.patch

funny_falcon (Yura Sokolov), 12/12/2016 10:39 AM

View differences:

load.c
return GET_VM()->loading_table;
}
struct feature_str {
const char* str;
size_t len;
};
static struct feature_str
to_feature_str(VALUE str)
{
struct feature_str res;
res.str = RSTRING_PTR(str);
res.len = RSTRING_LEN(str);
return res;
}
static struct feature_str
feature_subseq(struct feature_str orig, size_t beg, size_t len)
{
struct feature_str res;
res.str = orig.str + beg;
res.len = len;
assert(len <= orig.len);
return res;
}
static st_data_t
feature_key(struct feature_str str)
{
return st_hash(str.str, str.len, 0xfea7009e);
}
static void
features_index_add_single(VALUE short_feature, VALUE offset)
features_index_add_single(struct feature_str short_feature, VALUE offset)
{
struct st_table *features_index;
VALUE this_feature_index = Qnil;
char *short_feature_cstr;
st_data_t short_feature_key;
Check_Type(offset, T_FIXNUM);
Check_Type(short_feature, T_STRING);
short_feature_cstr = StringValueCStr(short_feature);
short_feature_key = feature_key(short_feature);
features_index = get_loaded_features_index_raw();
st_lookup(features_index, (st_data_t)short_feature_cstr, (st_data_t *)&this_feature_index);
st_lookup(features_index, short_feature_key, (st_data_t *)&this_feature_index);
if (NIL_P(this_feature_index)) {
st_insert(features_index, (st_data_t)ruby_strdup(short_feature_cstr), (st_data_t)offset);
st_insert(features_index, short_feature_key, (st_data_t)offset);
}
else if (RB_TYPE_P(this_feature_index, T_FIXNUM)) {
VALUE feature_indexes[2];
......
this_feature_index = (VALUE)xcalloc(1, sizeof(struct RArray));
RBASIC(this_feature_index)->flags = T_ARRAY; /* fake VALUE, do not mark/sweep */
rb_ary_cat(this_feature_index, feature_indexes, numberof(feature_indexes));
st_insert(features_index, (st_data_t)short_feature_cstr, (st_data_t)this_feature_index);
st_insert(features_index, short_feature_key, (st_data_t)this_feature_index);
}
else {
Check_Type(this_feature_index, T_ARRAY);
......
relies on for its fast lookup.
*/
static void
features_index_add(VALUE feature, VALUE offset)
features_index_add(VALUE featurev, VALUE offset)
{
VALUE short_feature;
const char *feature_str, *feature_end, *ext, *p;
struct feature_str feature, short_feature;
const char *feature_end, *ext, *p;
feature_str = StringValuePtr(feature);
feature_end = feature_str + RSTRING_LEN(feature);
StringValue(featurev);
feature = to_feature_str(featurev);
feature_end = feature.str + feature.len;
for (ext = feature_end; ext > feature_str; ext--)
for (ext = feature_end; ext > feature.str; ext--)
if (*ext == '.' || *ext == '/')
break;
if (*ext != '.')
......
long beg;
p--;
while (p >= feature_str && *p != '/')
while (p >= feature.str && *p != '/')
p--;
if (p < feature_str)
if (p < feature.str)
break;
/* Now *p == '/'. We reach this point for every '/' in `feature`. */
beg = p + 1 - feature_str;
short_feature = rb_str_subseq(feature, beg, feature_end - p - 1);
beg = p + 1 - feature.str;
short_feature = feature_subseq(feature, beg, feature_end - p - 1);
features_index_add_single(short_feature, offset);
if (ext) {
short_feature = rb_str_subseq(feature, beg, ext - p - 1);
short_feature = feature_subseq(feature, beg, ext - p - 1);
features_index_add_single(short_feature, offset);
}
}
features_index_add_single(feature, offset);
if (ext) {
short_feature = rb_str_subseq(feature, 0, ext - feature_str);
short_feature = feature_subseq(feature, 0, ext - feature.str);
features_index_add_single(short_feature, offset);
}
}
......
rb_ary_free(obj);
xfree((void *)obj);
}
xfree((char *)key);
return ST_DELETE;
}
......
st_table *loading_tbl, *features_index;
st_data_t data;
int type;
struct feature_str fstr;
fstr.str = feature;
fstr.len = strlen(feature);
if (fn) *fn = 0;
if (ext) {
......
features = get_loaded_features();
features_index = get_loaded_features_index();
st_lookup(features_index, (st_data_t)feature, (st_data_t *)&this_feature_index);
st_lookup(features_index, feature_key(fstr), (st_data_t *)&this_feature_index);
/* We search `features` for an entry such that either
"#{features[i]}" == "#{load_path[j]}/#{feature}#{e}"
for some j, or
......
rb_define_virtual_variable("$LOADED_FEATURES", get_loaded_features, 0);
vm->loaded_features = rb_ary_new();
vm->loaded_features_snapshot = rb_ary_tmp_new(0);
vm->loaded_features_index = st_init_strtable();
vm->loaded_features_index = st_init_numtable();
rb_define_global_function("load", rb_f_load, -1);
rb_define_global_function("require", rb_f_require, 1);
(1-1/2)