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

[PATCH 07/20] merge-ort: avoid repeating fill_tree_descriptor() on the same tree

From
Elijah Newren <newren@gmail.com>
Date
Oct 30, 2020, 03:41 UTC
Message-ID
<20201030034131.1479968-8-newren@gmail.com>
In-Reply-To
<20201030034131.1479968-1-newren@gmail.com>

Three-way merges, by their nature, are going to often have two or more trees match at a given subdirectory. We can avoid calling fill_tree_descriptor() on the same tree by checking when these trees match. Noting when various oids match will also be useful in other calculations and optimizations as well.

Signed-off-by: Elijah Newren <newren@gmail.com>
---
 merge-ort.c | 26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)
diff --git a/merge-ort.c b/merge-ort.c
index d652f1f062..7083388a47 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -99,6 +99,15 @@ static int collect_merge_info_callback(int n,
 	unsigned mbase_null = !(mask & 1);
 	unsigned side1_null = !(mask & 2);
 	unsigned side2_null = !(mask & 4);
+	unsigned side1_matches_mbase = (!side1_null && !mbase_null &&
+					names[0].mode == names[1].mode &&
+					oideq(&names[0].oid, &names[1].oid));
+	unsigned side2_matches_mbase = (!side2_null && !mbase_null &&
+					names[0].mode == names[2].mode &&
+					oideq(&names[0].oid, &names[2].oid));
+	unsigned sides_match = (!side1_null && !side2_null &&
+				names[1].mode == names[2].mode &&
+				oideq(&names[1].oid, &names[2].oid));
 
 	/* n = 3 is a fundamental assumption. */
 	if (n != 3)
@@ -154,10 +163,19 @@ static int collect_merge_info_callback(int n,
 		newinfo.pathlen = st_add3(newinfo.pathlen, p->pathlen, 1);
 
 		for (i = 0; i < 3; i++, dirmask >>= 1) {
-			const struct object_id *oid = NULL;
-			if (dirmask & 1)
-				oid = &names[i].oid;
-			buf[i] = fill_tree_descriptor(opt->repo, t + i, oid);
+			if (i == 1 && side1_matches_mbase)
+				t[1] = t[0];
+			else if (i == 2 && side2_matches_mbase)
+				t[2] = t[0];
+			else if (i == 2 && sides_match)
+				t[2] = t[1];
+			else {
+				const struct object_id *oid = NULL;
+				if (dirmask & 1)
+					oid = &names[i].oid;
+				buf[i] = fill_tree_descriptor(opt->repo,
+							      t + i, oid);
+			}
 		}
 
 		original_dir_name = opti->current_dir_name;
-- 
2.29.1.56.ga287c268e6.dirty
Previous: Elijah NewrenNext: Elijah Newren
Message 2 of 22 in “fundamentals of merge-ort implementation”
  1. 00/20 fundamentals of merge-ort implementationElijah Newren, Oct 30, 2020
  2. 07/20 merge-ort: avoid repeating fill_tree_descriptor() on the same treeElijah Newren, Oct 30, 2020
  3. 04/20 merge-ort: use histogram diffElijah Newren, Oct 30, 2020
  4. 01/20 merge-ort: setup basic internal data structuresElijah Newren, Oct 30, 2020
  5. 02/20 merge-ort: add some high-level algorithm structureElijah Newren, Oct 30, 2020
  6. 06/20 merge-ort: implement a very basic collect_merge_info()Elijah Newren, Oct 30, 2020
  7. 13/20 merge-ort: step 1 of tree writing -- record basenames, modes, and oidsElijah Newren, Oct 30, 2020
  8. 11/20 merge-ort: add a preliminary simple process_entries() implementationElijah Newren, Oct 30, 2020
  9. 12/20 merge-ort: have process_entries operate in a defined orderElijah Newren, Oct 30, 2020
  10. 10/20 merge-ort: avoid recursing into identical treesElijah Newren, Oct 30, 2020
  11. 14/20 merge-ort: step 2 of tree writing -- function to create tree objectElijah Newren, Oct 30, 2020
  12. 15/20 merge-ort: step 3 of tree writing -- handling subdirectories as we goElijah Newren, Oct 30, 2020
  13. 20/20 merge-ort: free data structures in merge_finalize()Elijah Newren, Oct 30, 2020
  14. 19/20 merge-ort: add implementation of record_unmerged_index_entries()Elijah Newren, Oct 30, 2020
  15. 18/20 tree: enable cmp_cache_name_compare() to be used elsewhereElijah Newren, Oct 30, 2020
  16. 17/20 merge-ort: add implementation of checkout()Elijah Newren, Oct 30, 2020
  17. 16/20 merge-ort: basic outline for merge_switch_to_result()Elijah Newren, Oct 30, 2020
  18. 05/20 merge-ort: add an err() function similar to one from merge-recursiveElijah Newren, Oct 30, 2020
  19. 09/20 merge-ort: record stage and auxiliary info for every pathElijah Newren, Oct 30, 2020
  20. 03/20 merge-ort: port merge_start() from merge-recursiveElijah Newren, Oct 30, 2020
  21. 08/20 merge-ort: compute a few more useful fields for collect_merge_infoElijah Newren, Oct 30, 2020
  22. Elijah NewrenOct 30, 2020

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.