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
180 180
    return GET_VM()->loading_table;
181 181
}
182 182

  
183
struct feature_str {
184
    const char* str;
185
    size_t len;
186
};
187

  
188
static struct feature_str
189
to_feature_str(VALUE str)
190
{
191
    struct feature_str res;
192
    res.str = RSTRING_PTR(str);
193
    res.len = RSTRING_LEN(str);
194
    return res;
195
}
196

  
197
static struct feature_str
198
feature_subseq(struct feature_str orig, size_t beg, size_t len)
199
{
200
    struct feature_str res;
201
    res.str = orig.str +  beg;
202
    res.len = len;
203
    assert(len <= orig.len);
204
    return res;
205
}
206

  
207
static st_data_t
208
feature_key(struct feature_str str)
209
{
210
    return st_hash(str.str, str.len, 0xfea7009e);
211
}
212

  
183 213
static void
184
features_index_add_single(VALUE short_feature, VALUE offset)
214
features_index_add_single(struct feature_str short_feature, VALUE offset)
185 215
{
186 216
    struct st_table *features_index;
187 217
    VALUE this_feature_index = Qnil;
188
    char *short_feature_cstr;
218
    st_data_t short_feature_key;
189 219

  
190 220
    Check_Type(offset, T_FIXNUM);
191
    Check_Type(short_feature, T_STRING);
192
    short_feature_cstr = StringValueCStr(short_feature);
221
    short_feature_key = feature_key(short_feature);
193 222

  
194 223
    features_index = get_loaded_features_index_raw();
195
    st_lookup(features_index, (st_data_t)short_feature_cstr, (st_data_t *)&this_feature_index);
224
    st_lookup(features_index, short_feature_key, (st_data_t *)&this_feature_index);
196 225

  
197 226
    if (NIL_P(this_feature_index)) {
198
	st_insert(features_index, (st_data_t)ruby_strdup(short_feature_cstr), (st_data_t)offset);
227
	st_insert(features_index, short_feature_key, (st_data_t)offset);
199 228
    }
200 229
    else if (RB_TYPE_P(this_feature_index, T_FIXNUM)) {
201 230
	VALUE feature_indexes[2];
......
204 233
	this_feature_index = (VALUE)xcalloc(1, sizeof(struct RArray));
205 234
	RBASIC(this_feature_index)->flags = T_ARRAY; /* fake VALUE, do not mark/sweep */
206 235
	rb_ary_cat(this_feature_index, feature_indexes, numberof(feature_indexes));
207
	st_insert(features_index, (st_data_t)short_feature_cstr, (st_data_t)this_feature_index);
236
	st_insert(features_index, short_feature_key, (st_data_t)this_feature_index);
208 237
    }
209 238
    else {
210 239
	Check_Type(this_feature_index, T_ARRAY);
......
221 250
   relies on for its fast lookup.
222 251
*/
223 252
static void
224
features_index_add(VALUE feature, VALUE offset)
253
features_index_add(VALUE featurev, VALUE offset)
225 254
{
226
    VALUE short_feature;
227
    const char *feature_str, *feature_end, *ext, *p;
255
    struct feature_str feature, short_feature;
256
    const char *feature_end, *ext, *p;
228 257

  
229
    feature_str = StringValuePtr(feature);
230
    feature_end = feature_str + RSTRING_LEN(feature);
258
    StringValue(featurev);
259
    feature = to_feature_str(featurev);
260
    feature_end = feature.str + feature.len;
231 261

  
232
    for (ext = feature_end; ext > feature_str; ext--)
262
    for (ext = feature_end; ext > feature.str; ext--)
233 263
	if (*ext == '.' || *ext == '/')
234 264
	    break;
235 265
    if (*ext != '.')
......
242 272
	long beg;
243 273

  
244 274
	p--;
245
	while (p >= feature_str && *p != '/')
275
	while (p >= feature.str && *p != '/')
246 276
	    p--;
247
	if (p < feature_str)
277
	if (p < feature.str)
248 278
	    break;
249 279
	/* Now *p == '/'.  We reach this point for every '/' in `feature`. */
250
	beg = p + 1 - feature_str;
251
	short_feature = rb_str_subseq(feature, beg, feature_end - p - 1);
280
	beg = p + 1 - feature.str;
281
	short_feature = feature_subseq(feature, beg, feature_end - p - 1);
252 282
	features_index_add_single(short_feature, offset);
253 283
	if (ext) {
254
	    short_feature = rb_str_subseq(feature, beg, ext - p - 1);
284
	    short_feature = feature_subseq(feature, beg, ext - p - 1);
255 285
	    features_index_add_single(short_feature, offset);
256 286
	}
257 287
    }
258 288
    features_index_add_single(feature, offset);
259 289
    if (ext) {
260
	short_feature = rb_str_subseq(feature, 0, ext - feature_str);
290
	short_feature = feature_subseq(feature, 0, ext - feature.str);
261 291
	features_index_add_single(short_feature, offset);
262 292
    }
263 293
}
......
270 300
	rb_ary_free(obj);
271 301
	xfree((void *)obj);
272 302
    }
273
    xfree((char *)key);
274 303
    return ST_DELETE;
275 304
}
276 305

  
......
384 413
    st_table *loading_tbl, *features_index;
385 414
    st_data_t data;
386 415
    int type;
416
    struct feature_str fstr;
417
    fstr.str = feature;
418
    fstr.len = strlen(feature);
387 419

  
388 420
    if (fn) *fn = 0;
389 421
    if (ext) {
......
399 431
    features = get_loaded_features();
400 432
    features_index = get_loaded_features_index();
401 433

  
402
    st_lookup(features_index, (st_data_t)feature, (st_data_t *)&this_feature_index);
434
    st_lookup(features_index, feature_key(fstr), (st_data_t *)&this_feature_index);
403 435
    /* We search `features` for an entry such that either
404 436
         "#{features[i]}" == "#{load_path[j]}/#{feature}#{e}"
405 437
       for some j, or
......
1196 1228
    rb_define_virtual_variable("$LOADED_FEATURES", get_loaded_features, 0);
1197 1229
    vm->loaded_features = rb_ary_new();
1198 1230
    vm->loaded_features_snapshot = rb_ary_tmp_new(0);
1199
    vm->loaded_features_index = st_init_strtable();
1231
    vm->loaded_features_index = st_init_numtable();
1200 1232

  
1201 1233
    rb_define_global_function("load", rb_f_load, -1);
1202 1234
    rb_define_global_function("require", rb_f_require, 1);
1203
-