summaryrefslogtreecommitdiff
path: root/pp_hot.c
diff options
context:
space:
mode:
authorCraig A. Berry <craigberry@mac.com>2014-03-21 19:29:38 -0500
committerCraig A. Berry <craigberry@mac.com>2014-03-21 20:55:03 -0500
commitb51c3e77dbb7e510319342a73163b3fbb59baf5a (patch)
tree6be52242d7cdb9f3cbe457508d597b7d476bcf5e /pp_hot.c
parent9e61631800d0659e1e5e30e02a500dcd56b566e9 (diff)
downloadperl-b51c3e77dbb7e510319342a73163b3fbb59baf5a.tar.gz
Reduce excessive stat calls in glob on VMS.
When PERL_EXTERNAL_GLOB is defined (currently only on VMS, or on other platforms when running miniperl), each item returned from the glob operation is checked against a set of glob metacharacters, and then, if it matches any of these characters, it's checked with lstat() to see if it actually exists. Then it's passed through if it exists but skipped otherwise. Presumably this is because returning the pattern unchanged is how a shell glob indicates "no match." It appears that the lstat() is necessary because glob metacharacters are almost always valid filename characters on Unix, so it's the only way to distinguish a funny-looking but real filename from the no match case (oops -- indeterminate grammar). Since these filenames are rare on Unix, lstat() is seldom called. Enter VMS, where "external glob" is neither external, nor is it actually a glob. It is a native wildcard-matching search built into Perl with vms/vms.c's Perl_vms_start_glob(), which does return the original pattern when there is no match, but that pattern will only contain native wildcard characters, so the check for glob metacharacters is really not the right thing to be doing. Moreover, glob metacharacters such as dollar signs, brackets, and semicolons are extremely common in native VMS paths, so in many common scenarios, the lstat() to see if the file really exists gets triggered for every single file, which is expensive. This commit replaces, on VMS only, the check for glob metacharacters with a check for VMS wildcard characters. A simple glob of a Perl source tree becomes 60% faster on the first iteration and 80% faster on subsequent iterations. Thanks to Hein van den Heuvel, who reported the problem and explained that a search operation should only be looking at directory files, whereas a stat does I/O to the individual file header, resulting in a massive increase in unnecessary I/O. This closes [perl #121440].
Diffstat (limited to 'pp_hot.c')
-rw-r--r--pp_hot.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/pp_hot.c b/pp_hot.c
index c3637cd381..ac69bc7208 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -1698,7 +1698,11 @@ Perl_do_readline(pTHX)
}
}
for (t1 = SvPVX_const(sv); *t1; t1++)
+#ifdef __VMS
+ if (strchr("*%?", *t1))
+#else
if (strchr("$&*(){}[]'\";\\|?<>~`", *t1))
+#endif
break;
if (*t1 && PerlLIO_lstat(SvPVX_const(sv), &PL_statbuf) < 0) {
(void)POPs; /* Unmatched wildcard? Chuck it... */