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 <rene.scharfe@lsrfire.ath.cx>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
René Scharfe 2009-01-10 00:18:34 +01:00 committed by Junio C Hamano
parent fb62eb7fab
commit c822255cfc
2 changed files with 26 additions and 4 deletions

29
grep.c
View file

@ -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);

1
grep.h
View file

@ -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 {