From: René Scharfe Date: Fri, 9 Jan 2009 23:18:34 +0000 (+0100) Subject: grep: don't call regexec() for fixed strings X-Git-Tag: v1.6.2-rc0~107^2~4 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=c822255cfc1ac83daeeeee1647e3c775450c830c;p=git.git grep: don't call regexec() for fixed strings Add the new flag "fixed" to struct grep_pat and set it if the pattern is doesn't contain any regex control characters in addition to if the flag -F/--fixed-strings was specified. This gives a nice speed up on msysgit, where regexec() seems to be extra slow. Before (best of five runs): $ time git grep grep v1.6.1 >/dev/null real 0m0.552s user 0m0.000s sys 0m0.000s $ time git grep -F grep v1.6.1 >/dev/null real 0m0.170s user 0m0.000s sys 0m0.015s With the patch: $ time git grep grep v1.6.1 >/dev/null real 0m0.173s user 0m0.000s sys 0m0.000s The difference is much smaller on Linux, but still measurable. Signed-off-by: Rene Scharfe Signed-off-by: Junio C Hamano --- diff --git a/grep.c b/grep.c index 22a56b5d5..6485760ff 100644 --- a/grep.c +++ b/grep.c @@ -28,9 +28,31 @@ void append_grep_pattern(struct grep_opt *opt, const char *pat, p->next = NULL; } +static int isregexspecial(int c) +{ + return isspecial(c) || c == '$' || c == '(' || c == ')' || c == '+' || + c == '.' || c == '^' || c == '{' || c == '|'; +} + +static int is_fixed(const char *s) +{ + while (!isregexspecial(*s)) + s++; + return !*s; +} + static void compile_regexp(struct grep_pat *p, struct grep_opt *opt) { - int err = regcomp(&p->regexp, p->pattern, opt->regflags); + int err; + + if (opt->fixed || is_fixed(p->pattern)) + p->fixed = 1; + if (opt->regflags & REG_ICASE) + p->fixed = 0; + if (p->fixed) + return; + + err = regcomp(&p->regexp, p->pattern, opt->regflags); if (err) { char errbuf[1024]; char where[1024]; @@ -159,8 +181,7 @@ void compile_grep_patterns(struct grep_opt *opt) case GREP_PATTERN: /* atom */ case GREP_PATTERN_HEAD: case GREP_PATTERN_BODY: - if (!opt->fixed) - compile_regexp(p, opt); + compile_regexp(p, opt); break; default: opt->extended = 1; @@ -314,7 +335,7 @@ static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol } again: - if (!opt->fixed) { + if (!p->fixed) { regex_t *exp = &p->regexp; hit = !regexec(exp, bol, ARRAY_SIZE(pmatch), pmatch, 0); diff --git a/grep.h b/grep.h index 45a222d90..5102ce335 100644 --- a/grep.h +++ b/grep.h @@ -30,6 +30,7 @@ struct grep_pat { const char *pattern; enum grep_header_field field; regex_t regexp; + unsigned fixed:1; }; enum grep_expr_node {