Subject: Re: Why is "git tag --contains" so slow?

From: "Shawn O. Pearce" <[email-masked]>
Date: Wed, 30 Jun 2010 17:58:54 -0700

Theodore Ts'o <[email-masked]> wrote:
> 
> I'm trying to write a script that can determine the first kernel release
> (i.e., a tag of that matchs v2.6.*) that contains a particular commit.
> 
> I can do this using "git tag --contains <commit-id>", but it's quite
> slow.  It takes something like 8-9 seconds.  (8.5 seconds of user time,
> 8.6 times of wall clock, to be precise).
> 
> I can get the information much faster using "gitk -1 <commit-id>", which
> finishes painting the screen in under 2 seconds, but that throws up a
> GUI and then a human has to pull the information out using their eyes.
> (Yeah, or I could figure out where in the 11,631 lines of Tcl script the
> "preceeds" line is calculated, but I figured I'd ask here first.)
> 
> Is there a better way of calculating what I want from the command line
> using the built-in native git tools?  And if so, why is git tag
> --contains apparently 4 times slower than gitk at performing this task?

gitk keeps a cache of this stuff in .git/gitk.cache.  I'll bet its
pulling from cache here, which is why it snaps so fast.

Without the cache is expensive, which is what 'git tag --contains'
is doing.  The code walks back from each tag tracing along the commit
parent pointers, keeping track of the nearest tag name that can reach
any given commit.  When it finds your commit, it stops and outputs.

Since this stuff can't change unless the refs change, yes, it can be
cached easily.  But nobody has done caching for this in Git itself,
only in Tcl for gitk.  :-\

-- 
Shawn.