Hi, On Thu, 14 Dec 2006, Junio C Hamano wrote: > Johannes Schindelin <Johannes.Schindelin@xxxxxx> writes: > > > git-show-ref traverses every single _local_ tag when called. This is to > > overcome the problem that tags can be packed now, so a simple file > > existence check is not sufficient. > > Is "traverses every single _local_ tag" a fact? It might go > through every single _local_ (possibly stale) packed tag in > memory but it should not traverse $GIT_DIR/refs/tags. > > If I recall correctly, show-ref (1) first checks the filesystem > "$GIT_DIR/$named_ref" and says Ok if found and valid; otherwise > (2) checks packed refs (reads $GIT_DIR/packed-refs if not > already). If I read builtin-show-ref.c correctly, it _always_ calls for_each_ref(show_ref, NULL); The only reason that the loop in for_each_ref can stop early is if show_ref returns something different than 0. But it does not! Every single return in show_ref() returns 0. It does not matter, though (see below). > So that would be at most one open (which may fail in (1)) and one > open+read (in (2)). Unless we are talking about fork+exec overhead, > that "traverse" should be reasonably fast. > > Where is the bottleneck? The problem is that so many stat()s _do_ take time. Again, if I read the code correctly, it not only stat()s every loose ref, but also resolves the refs in get_ref_dir(), which is called from get_loose_refs(), which is unconditionally called in for_each_ref(). Even if the refs are packed, it takes quite _long_ (I confirmed this). And it is not at all necessary! Instead of a O(n^2) we can easily reduce this to O(n*log(n)), and we can reduce the n fork()&exec()s of git-show-ref by a single one. Ciao, Dscho - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html