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

Re: [PATCH 3/3] Make clear_commit_marks() clean harder

From
Linus Torvalds <torvalds@osdl.org>
Date
Jul 3, 2006, 17:05 UTC
Message-ID
<Pine.LNX.4.64.0607030957420.12404@g5.osdl.org>
In-Reply-To
<Pine.LNX.4.63.0607031553570.29667@wbgn013.biozentrum.uni-wuerzburg.de>
On Mon, 3 Jul 2006, Johannes Schindelin wrote:
Show 13 quoted lines
> 
> On Mon, 3 Jul 2006, Junio C Hamano wrote:
> 
> > Rene Scharfe <rene.scharfe@lsrfire.ath.cx> writes:
> > 
> > > Don't care if objects have been parsed or not and don't stop when we
> > > reach a commit that is already clean -- its parents could be dirty.
> > 
> > There is something quite wrong with this patch.
> 
> I always had the feeling that it was wrong to traverse not-yet-parsed 
> parents: How could a revision walk possibly come to a certain commit 
> without at least one continuous history of now-parsed objects?
No, that's not the problem.

The problem is that if we unconditionally traverse parents - whether parsed or not - any merge will basically result in a 2* expansion of the working set: we'll traverse all children twice (whether they meet again or not).

So the cost of doign unconditional traversals of parents basically approaches 2^n, where 'n' is the number of merges.

Now, the fact that we only traverse parents without adding new ones (and the decision on whether it is parsed or not is irrelevant - the only relevant part being that we don't parse any _new_ ones) means that each commit itself is very cheap to traverse, but O(2^n) ends up meaning that even a small constant will eventually be pretty big.

The proper fix is _not_ to add the "object->parsed" check (which is silly, wrong, and doesn't fix anything at all), but to add a check for whether the object has been seen or not.

In the case of clearing flags, you have two choices:
 - _set_ a new flag ("already cleared"). This would work - once - but is 
   obviously pretty bad.
   This is what we do in all the other cases. We usually call the flag 
   SEEN or similar.
 - depend on the flags being "dense", and saying that we depend on the 
   fact that in order for any of the flags to have been set in the first 
   place, at least _one_ of them needs to be set in the path leading up to 
   that commit.

Now, for the specific case of get_merge_bases(), the flags _are_ dense. Individual flags may not be (eg the "UNINTERESTING" flag, whatever it's called, will not be dense), but the question of "is _any_ of the flags we care about set" _will_ be dense.

As such, adding a
	/* Have we already cleared this? */
	if (!(mask & object->flags))
		return;
	object->flags &= ~mask;

to the traversal function will fix the O(m+2^n) behaviour, and turn the traversal into O(m+n) (where "n" is the number of merges, and "m" is the total number of commits).

		Linus
Previous: Johannes SchindelinNext: Johannes Schindelin
Message 33 of 49 in “A note on merging conflicts..”
  1. Linus TorvaldsJul 1, 2006
  2. Junio C HamanoJul 1, 2006
  3. Linus TorvaldsJul 1, 2006
  4. Linus TorvaldsJul 1, 2006
  5. Rene ScharfeJul 1, 2006
  6. Johannes SchindelinJul 1, 2006
  7. Linus TorvaldsJul 1, 2006
  8. Rene ScharfeJul 1, 2006
  9. J. Bruce FieldsJul 1, 2006
  10. Linus TorvaldsJul 1, 2006
  11. Daniel BarkalowJul 1, 2006
  12. Linus TorvaldsJul 1, 2006
  13. Daniel BarkalowJul 1, 2006
  14. Daniel BarkalowJul 1, 2006
  15. Rene ScharfeJul 2, 2006
  16. Daniel BarkalowJul 2, 2006
  17. Linus TorvaldsJul 2, 2006
  18. Jakub NarebskiJul 1, 2006
  19. Linus TorvaldsJul 1, 2006
  20. Junio C HamanoJul 1, 2006
  21. Rene ScharfeJul 1, 2006
  22. Junio C HamanoJul 1, 2006
  23. Johannes SchindelinJul 1, 2006
  24. Linus TorvaldsJul 1, 2006
  25. Junio C HamanoJul 1, 2006
  26. Junio C HamanoJul 1, 2006
  27. 1/3 Add get_merge_bases_clean()Rene Scharfe, Jul 1, 2006
  28. Johannes SchindelinJul 1, 2006
  29. 2/3 Add '...' operator for revisionsRene Scharfe, Jul 1, 2006
  30. 3/3 Make clear_commit_marks() clean harderRene Scharfe, Jul 1, 2006
  31. Junio C HamanoJul 3, 2006
  32. Johannes SchindelinJul 3, 2006
  33. Linus TorvaldsJul 3, 2006
  34. Johannes SchindelinJul 3, 2006
  35. Junio C HamanoJul 3, 2006
  36. Johannes SchindelinJul 3, 2006
  37. Linus TorvaldsJul 3, 2006
  38. Johannes SchindelinJul 4, 2006
  39. Junio C HamanoJul 4, 2006
  40. 4/3 Fold get_merge_bases_clean() into get_merge_bases()Rene Scharfe, Jul 2, 2006
  41. Johannes SchindelinJul 2, 2006
  42. Linus TorvaldsJul 2, 2006
  43. Rene ScharfeJul 2, 2006
  44. Junio C HamanoJul 2, 2006
  45. Rene ScharfeJul 2, 2006
  46. Rene ScharfeJul 2, 2006
  47. Linus TorvaldsJul 2, 2006
  48. Linus TorvaldsJul 2, 2006
  49. Junio C HamanoJul 7, 2006

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.