git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH 8/8] wildmatch: advance faster in <asterisk> + <literal> patterns

From
Junio C Hamano <gitster@pobox.com>
Date
Dec 28, 2012, 06:24 UTC
Message-ID
<7vpq1uk82q.fsf@alter.siamese.dyndns.org>
In-Reply-To
<1356163028-29967-9-git-send-email-pclouds@gmail.com>
Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:
Show 28 quoted lines
> compat, '*/*/*' on linux-2.6.git file list 2000 times, before:
> wildmatch 7s 985049us
> fnmatch   2s 735541us or 34.26% faster
>
> and after:
> wildmatch 4s 492549us
> fnmatch   0s 888263us or 19.77% slower
>
> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
> ---
>  wildmatch.c | 21 +++++++++++++++++++++
>  1 file changed, 21 insertions(+)
>
> diff --git a/wildmatch.c b/wildmatch.c
> index 3794c4d..68b02e4 100644
> --- a/wildmatch.c
> +++ b/wildmatch.c
> @@ -132,6 +132,27 @@ static int dowild(const uchar *p, const uchar *text, unsigned int flags)
>  			while (1) {
>  				if (t_ch == '\0')
>  					break;
> +				/*
> +				 * Try to advance faster when an asterisk is
> +				 * followed by a literal. We know in this case
> +				 * that the the string before the literal
> +				 * must belong to "*".
> +				 */
> +				if (!is_glob_special(*p)) {

So far, we have looked at "*x" or "**x" in the pattern, p points at 'x' (not an asterisk), and we have "text" to match. For "text" to match this pattern, the earlier part of it that is consumed to match the asterisk must be followed by "x". "special" tells us if we are allowed to treat '/' as matching the asterisk.

> +					p_ch = *p;
> +					if ((flags & WM_CASEFOLD) && ISUPPER(p_ch))
> +						p_ch = tolower(p_ch);

That "x" in the example is picked up here and stored in "p_ch". Let's skip over "text" and find that "x" in there.

> +					while ((t_ch = *text) != '\0' &&
> +					       (!(flags & WM_PATHNAME) || t_ch != '/')) {
Why do we look at (flags & WM_PATHMAME) and not "special" here?
> +						if ((flags & WM_CASEFOLD) && ISUPPER(t_ch))
> +							t_ch = tolower(t_ch);
> +						if (t_ch == p_ch)
> +							break;
Found it.
> +						text++;
> +					}
> +					if (t_ch != p_ch)
> +						return WM_NOMATCH;

If we did not find that "x", then "**x" or "*x" can never match. OK. And at this point "text" points at that "x" we found, and "p" points at "x" after the asterisk in the pattern.

Looks good so far.  Thanks.
> +				}
>  				if ((matched = dowild(p, text,  flags)) != WM_NOMATCH) {
>  					if (!special || matched != WM_ABORT_TO_STARSTAR)
>  						return matched;
Previous: Nguyễn Thái Ngọc DuyNext: Nguyen Thai Ngoc Duy
Message 13 of 14 in “fnmatch replacement step 1”
  1. 0/8 fnmatch replacement step 1Nguyễn Thái Ngọc Duy, Dec 22, 2012
  2. 1/8 compat/fnmatch: respect NO_FNMATCH* even on glibcNguyễn Thái Ngọc Duy, Dec 22, 2012
  3. 2/8 wildmatch: rename constants and update prototypeNguyễn Thái Ngọc Duy, Dec 22, 2012
  4. Junio C HamanoDec 26, 2012
  5. 3/8 wildmatch: make dowild() take arbitrary flagsNguyễn Thái Ngọc Duy, Dec 22, 2012
  6. 4/8 wildmatch: support "no FNM_PATHNAME" modeNguyễn Thái Ngọc Duy, Dec 22, 2012
  7. Junio C HamanoDec 28, 2012
  8. Nguyen Thai Ngoc DuyDec 28, 2012
  9. 5/8 test-wildmatch: add "perf" command to compare wildmatch and fnmatchNguyễn Thái Ngọc Duy, Dec 22, 2012
  10. 6/8 Makefile: add USE_WILDMATCH to use wildmatch as fnmatchNguyễn Thái Ngọc Duy, Dec 22, 2012
  11. 7/8 wildmatch: make a special case for "*/" with FNM_PATHNAMENguyễn Thái Ngọc Duy, Dec 22, 2012
  12. 8/8 wildmatch: advance faster in <asterisk> + <literal> patternsNguyễn Thái Ngọc Duy, Dec 22, 2012
  13. Junio C HamanoDec 28, 2012
  14. Nguyen Thai Ngoc DuyDec 28, 2012

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.