Project

General

Profile

Bug #13167 ยป 0001-dir.c-performance-fix-with-braces-using-cache.patch

h.shirosaki (Hiroshi Shirosaki), 09/11/2017 02:23 PM

View differences:

dir.c
1776 1776
# error not implemented
1777 1777
#endif
1778 1778

  
1779
#if defined HAVE_GETATTRLIST || defined _WIN32
1780
struct real_path {
1781
    char *path;
1782
    rb_pathtype_t type;
1783
};
1784

  
1785
static char *
1786
replace_real_basename_with_cache(char *path, long base, rb_encoding *enc, int norm_p, int flags,
1787
				 rb_pathtype_t *type, st_table *cached_paths)
1788
{
1789
    struct real_path *real_path;
1790
    st_data_t key = (st_data_t)path;
1791

  
1792
    if (cached_paths && st_lookup(cached_paths, key, (st_data_t *)&real_path)) {
1793
	path = ruby_strdup(real_path->path);
1794
	*type = real_path->type;
1795
    }
1796
    else {
1797
	path = replace_real_basename(path, base, enc, norm_p, flags, type);
1798
	if (cached_paths) {
1799
	    real_path = GLOB_ALLOC(struct real_path);
1800
	    real_path->path = ruby_strdup(path);
1801
	    real_path->type = *type;
1802
	    st_insert(cached_paths, key, (st_data_t)real_path);
1803
	}
1804
    }
1805
    return path;
1806
}
1807
#endif
1808

  
1779 1809
#ifndef S_ISDIR
1780 1810
#   define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
1781 1811
#endif
......
1888 1918
    int flags,
1889 1919
    const ruby_glob_funcs_t *funcs,
1890 1920
    VALUE arg,
1921
    st_table *cached_paths,
1891 1922
    rb_encoding *enc)
1892 1923
{
1893 1924
    struct stat st;
......
2093 2124
	    }
2094 2125

  
2095 2126
	    status = glob_helper(fd, buf, baselen, name - buf - baselen + namlen, 1,
2096
				 new_pathtype, new_beg, new_end,
2097
				 flags, funcs, arg, enc);
2127
				 new_pathtype, new_beg, new_end, flags, funcs,
2128
				 arg, cached_paths, enc);
2098 2129
	    GLOB_FREE(buf);
2099 2130
	    GLOB_FREE(new_beg);
2100 2131
	    if (status) break;
......
2152 2183
#if USE_NAME_ON_FS == USE_NAME_ON_FS_REAL_BASENAME
2153 2184
		if ((*cur)->type == ALPHA) {
2154 2185
		    long base = pathlen + (dirsep != 0);
2155
		    buf = replace_real_basename(buf, base, enc, IF_NORMALIZE_UTF8PATH(1)+0,
2156
						flags, &new_pathtype);
2186
		    buf = replace_real_basename_with_cache(buf, base, enc,
2187
							   IF_NORMALIZE_UTF8PATH(1)+0,
2188
							   flags, &new_pathtype,
2189
							   cached_paths);
2157 2190
		    if (!buf) break;
2158 2191
		}
2159 2192
#endif
2160 2193
		status = glob_helper(fd, buf, baselen,
2161 2194
				     namelen + strlen(buf + pathlen), 1,
2162 2195
				     new_pathtype, new_beg, new_end,
2163
				     flags, funcs, arg, enc);
2196
				     flags, funcs, arg, cached_paths, enc);
2164 2197
		GLOB_FREE(buf);
2165 2198
		GLOB_FREE(new_beg);
2166 2199
		if (status) break;
......
2176 2209
static int
2177 2210
ruby_glob0(const char *path, int fd, const char *base, int flags,
2178 2211
	   const ruby_glob_funcs_t *funcs, VALUE arg,
2179
	   rb_encoding *enc)
2212
	   st_table *cached_paths, rb_encoding *enc)
2180 2213
{
2181 2214
    struct glob_pattern *list;
2182 2215
    const char *root, *start;
......
2211 2244
    }
2212 2245
    status = glob_helper(fd, buf, baselen, n-baselen, dirsep,
2213 2246
			 path_unknown, &list, &list + 1,
2214
			 flags, funcs, arg, enc);
2247
			 flags, funcs, arg, cached_paths, enc);
2215 2248
    glob_free_pattern(list);
2216 2249
    GLOB_FREE(buf);
2217 2250

  
......
2225 2258
    funcs.match = func;
2226 2259
    funcs.error = NULL;
2227 2260
    return ruby_glob0(path, AT_FDCWD, 0, flags & ~GLOB_VERBOSE,
2228
		      &funcs, arg, rb_ascii8bit_encoding());
2261
		      &funcs, arg, NULL, rb_ascii8bit_encoding());
2229 2262
}
2230 2263

  
2231 2264
static int
......
2254 2287
    args.enc = rb_ascii8bit_encoding();
2255 2288

  
2256 2289
    status = ruby_glob0(path, AT_FDCWD, 0, GLOB_VERBOSE, &rb_glob_funcs,
2257
			(VALUE)&args, args.enc);
2290
			(VALUE)&args, NULL, args.enc);
2258 2291
    if (status) GLOB_JUMP_TAG(status);
2259 2292
}
2260 2293

  
......
2343 2376
{
2344 2377
    struct brace_args *arg = (struct brace_args *)val;
2345 2378

  
2346
    return ruby_glob0(path, AT_FDCWD, 0, arg->flags, &arg->funcs, arg->value, enc);
2379
    return ruby_glob0(path, AT_FDCWD, 0, arg->flags, &arg->funcs, arg->value, NULL, enc);
2347 2380
}
2348 2381

  
2349 2382
int
......
2369 2402
    struct glob_args glob;
2370 2403
    int flags;
2371 2404
    int fd;
2405
    st_table *cached_paths;
2372 2406
};
2373 2407

  
2374 2408
static int
......
2377 2411
    struct push_glob_args *arg = (struct push_glob_args *)val;
2378 2412

  
2379 2413
    return ruby_glob0(path, arg->fd, arg->glob.base, arg->flags, &rb_glob_funcs,
2380
		      (VALUE)&arg->glob, enc);
2414
		      (VALUE)&arg->glob, arg->cached_paths, enc);
2381 2415
}
2382 2416

  
2417
#if defined HAVE_GETATTRLIST || defined _WIN32
2418
static int
2419
free_cached_paths(st_data_t key, st_data_t val, st_data_t arg)
2420
{
2421
    GLOB_FREE((struct real_path *)val);
2422
    return ST_DELETE;
2423
}
2424
#endif
2425

  
2383 2426
static int
2384 2427
push_glob(VALUE ary, VALUE str, VALUE base, int flags)
2385 2428
{
2386 2429
    struct push_glob_args args;
2387 2430
    rb_encoding *enc = rb_enc_get(str);
2431
    int status;
2388 2432

  
2389 2433
#if defined _WIN32 || defined __APPLE__
2390 2434
    str = rb_str_encode_ospath(str);
......
2416 2460
    enc = rb_utf8_encoding();
2417 2461
#endif
2418 2462

  
2419
    return ruby_brace_expand(RSTRING_PTR(str), flags,
2420
			     push_caller, (VALUE)&args, enc, str);
2463
#if defined HAVE_GETATTRLIST || defined _WIN32
2464
    args.cached_paths = st_init_strtable();
2465
#endif
2466
    status = ruby_brace_expand(RSTRING_PTR(str), flags,
2467
			       push_caller, (VALUE)&args, enc, str);
2468
#if defined HAVE_GETATTRLIST || defined _WIN32
2469
    st_foreach(args.cached_paths, free_cached_paths, 0);
2470
    st_free_table(args.cached_paths);
2471
#endif
2472
    return status;
2421 2473
}
2422 2474

  
2423 2475
static VALUE
2424
-