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

Re: git and larger trees, not so fast?

From
Linus Torvalds <torvalds@linux-foundation.org>
Date
Aug 9, 2007, 17:38 UTC
Message-ID
<alpine.LFD.0.999.0708091015500.25146@woody.linux-foundation.org>
In-Reply-To
<alpine.LFD.0.999.0708090948250.25146@woody.linux-foundation.org>
On Thu, 9 Aug 2007, Linus Torvalds wrote:
Show 13 quoted lines
> 
> Doing an ltrace on it shows tons and tons of:
> 
> 	...
> 	strlen("35")
> 	strlen("349")
> 	calloc(1, 72)
> 	memcpy(0x73034e, "10/", 3)
> 	memcpy(0x730351, "349", 4)
> 	memmove(0x2ab637f41e80, 0x2ab637f41e78, 781768)
> 	...
> 
> but I haven't looked at where they come from yet.

Ouch. It's the diffing between HEAD and the index, and it's all from "add_index_entry()", which sorts the index array using an insertion sort. So when the index array gets large, that sort spends all its time in huge memmove() calls.

The silly thing, of course, is that we don't even "need" to do that: both the index and the trees are really sorted already, so we could just interleave them. But since we read them separately, the thing just sucks.

We've fixed other similar cases of this we had (diffing trees against each other) by walking the trees together, but the "index vs tree" diff (and merge) is the one remaining place where we still use the original stupid algorithm. So you'll see this performance problem for

 - diff tree against index ("git diff HEAD"
 - merge tree into index ("git read-tree -m HEAD")
which both do the stupid index/tree filling.

So this is all O(n**2), which is why we haven't reacted very much - it doesn't show up nearly as much with the kernel. Also, with a smaller set of files, it would tends to fit in the L2 cache of most competent CPU's. So not only is it n**2, you get the cache trashing behaviour too, and that, I think, is what really causes it to fall off the cliff edge!

Gaah. This shouldn't be *that* hard to fix, but I'm not entirely sure I'll have time today.

Diffing the index against the tree *should* be instantaneous. It should be no more costly than reading the tree itself (which is 0.191 seconds for me: test "git read-tree -m HEAD" vs "git read-tree HEAD") and reading the index (which is almost instantaneous - the only way I can test it is by doing something like "git update-index --refresh", and that's 0.131 seconds, but that includes all the 100,000 "lstat()" calls).

So basically, we're spending several seconds just doing stupid make-believe work and moving the index array around. Ouch.

Anyway, the good news is that this is by no means fundamental. It's a small and stupid detail. The only thing that makes it at all painful is that this is in some low-level crud that we haven't touched in *ages*, so I've long since swapped out all my recollection of how we do it.

(We basically do:
	read_cache();
followed by
	unpack_trees();

and each of those *on*its*own* is pretty cheap, but when we unpack trees into an already populated index, the end result is ugly.

			Linus
Previous: Linus TorvaldsNext: Junio C Hamano
Message 3 of 37 in “git and larger trees, not so fast?”
  1. moeAug 9, 2007
  2. Linus TorvaldsAug 9, 2007
  3. Linus TorvaldsAug 9, 2007
  4. Junio C HamanoAug 9, 2007
  5. Linus TorvaldsAug 9, 2007
  6. Junio C HamanoAug 9, 2007
  7. Junio C HamanoAug 9, 2007
  8. SeanAug 9, 2007
  9. Junio C HamanoAug 9, 2007
  10. Linus TorvaldsAug 9, 2007
  11. Linus TorvaldsAug 9, 2007
  12. Junio C HamanoAug 9, 2007
  13. Junio C HamanoAug 9, 2007
  14. Junio C HamanoAug 10, 2007
  15. Linus TorvaldsAug 10, 2007
  16. Junio C HamanoAug 10, 2007
  17. Linus TorvaldsAug 10, 2007
  18. Junio C HamanoAug 10, 2007
  19. Junio C HamanoAug 10, 2007
  20. Linus TorvaldsAug 10, 2007
  21. Linus TorvaldsAug 10, 2007
  22. Fix "git commit directory/" performance anomalyLinus Torvalds, Aug 10, 2007
  23. Linus TorvaldsAug 10, 2007
  24. Junio C HamanoAug 10, 2007
  25. Linus TorvaldsAug 10, 2007
  26. Daniel BarkalowAug 10, 2007
  27. Linus TorvaldsAug 9, 2007
  28. David KastrupAug 9, 2007
  29. Linus TorvaldsAug 10, 2007
  30. Linus TorvaldsAug 11, 2007
  31. Fernando J. PeredaAug 11, 2007
  32. Linus TorvaldsAug 11, 2007
  33. Fernando J. PeredaAug 11, 2007
  34. Linus TorvaldsAug 11, 2007
  35. David KastrupAug 11, 2007
  36. moeAug 11, 2007
  37. moeAug 23, 2007

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.