Hi,
In message "[ruby-talk:10778] perform. of Dir["**/*"]"
on 01/02/13, "Richard Hensh" <hensh / math.msu.edu> writes:
|Now that someone has straightened me out on the use of **, I have a
|performance question. Running the following script on my C: drive took about
|497 seconds. The drive contains 32701 files. Is this slow?
Slow. Since it had to create 32701 string objects, GC intervals
became burden. On my Linux box,
% ruby -e 'p Dir.glob("**/*").length'
took 1m43sec. OTOH,
% ruby -e 'GC.disable; p Dir.glob("**/*").length'
took 1m13sec.
Then I hacked to reduce memory consumption by using block,
so that now
% ruby -e 'GC.disable; n = 0; p Dir.glob("**/*"){n+=1}; p n'
takes 4.08sec. Here's the patch from the latest.
matz.
--- dir.c~ Mon Nov 20 10:24:22 2000
+++ dir.c Wed Feb 14 03:29:05 2001
@@ -679,7 +709,14 @@
char *path;
VALUE ary;
{
- rb_ary_push(ary, rb_tainted_str_new2(path));
+ VALUE str = rb_tainted_str_new2(path);
+
+ if (ary) {
+ rb_ary_push(ary, str);
+ }
+ else {
+ rb_yield(str);
+ }
}
static void
@@ -753,10 +790,12 @@
char buffer[MAXPATHLEN], *buf = buffer;
char *t;
int nest;
- VALUE ary;
+ VALUE ary = 0;
Check_SafeStr(str);
- ary = rb_ary_new();
+ if (!rb_block_given_p()) {
+ ary = rb_ary_new();
+ }
if (RSTRING(str)->len >= MAXPATHLEN)
buf = xmalloc(RSTRING(str)->len + 1);
@@ -783,14 +826,6 @@
}
if (buf != buffer)
free(buf);
- if (rb_block_given_p()) {
- long len = RARRAY(ary)->len;
- VALUE *ptr = RARRAY(ary)->ptr;
-
- while (len--) {
- rb_yield(*ptr++);
- }
- }
return ary;
}