[PATCH] cat: increase perf when catting without patterns

FUJIWARA Katsunori foozy at lares.dti.ne.jp
Sun Jan 12 08:41:13 CST 2014


At Fri, 10 Jan 2014 19:17:30 -0800,
Durham Goode wrote:
> 
> # HG changeset patch
> # User Durham Goode <durham at fb.com>
> # Date 1389405865 28800
> #      Fri Jan 10 18:04:25 2014 -0800
> # Node ID c4d55205c7d81950d631debed3c044c82e87cbd9
> # Parent  d2704c48f4176d8cd6f21d33500820d44763585c
> cat: increase perf when catting without patterns
> 
> When running 'hg cat -r . <file>' it was doing an expensive ctx.walk(m). It's
> much faster to just read that file directly. In our repo it shaves 60% off the
> 'hg cat' time.
> 
> diff --git a/mercurial/commands.py b/mercurial/commands.py
> --- a/mercurial/commands.py
> +++ b/mercurial/commands.py
> @@ -1151,15 +1151,32 @@
>      ctx = scmutil.revsingle(repo, opts.get('rev'))
>      err = 1
>      m = scmutil.match(ctx, (file1,) + pats, opts)
> -    for abs in ctx.walk(m):
> +
> +    def write(path):
>          fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
> -                                 pathname=abs)
> -        data = ctx[abs].data()
> +                                 pathname=path)
> +        data = ctx[path].data()
>          if opts.get('decode'):
> -            data = repo.wwritedata(abs, data)
> +            data = repo.wwritedata(path, data)
>          fp.write(data)
>          fp.close()
> -        err = 0
> +
> +    files = set(m.files())
> +    files.discard('.')
> +    if files and not m.anypats():
> +        for file in sorted(list(files)):
> +            try:
> +                write(file)
> +                err = 0

Before this patch, "hg cat" matches the pattern without explicit kind
(like "glob:") against not only file but also directory, because
default pattern kind of "scmutil.match()" is "relpath".

But this patch seems to match the pattern without explicit kind
against only file. This may break backward compatibility.


BTW, pattern matching of this patch seems to be similar to one of
"filelog()"/"contains()" revset predicates. I'm just working for the
patch to add explanation about "the pattern without explicit kind is
not matched against directory for efficiency" for online help of them :-)

> +            except error.ManifestLookupError:
> +                # It's significantly cheaper to catch the exception than it
> +                # is to do a 'file in ctx' check, due to makefileobj using
> +                # manifest.find instead of manifest.read
> +                m.bad(file, _('no such file in rev %s') % ctx)
> +    else:
> +        for abs in ctx.walk(m):
> +            write(abs)
> +            err = 0
>      return err
>  
>  @command('^clone',
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
> 

----------------------------------------------------------------------
[FUJIWARA Katsunori]                             foozy at lares.dti.ne.jp


More information about the Mercurial-devel mailing list