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

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

From
Elijah Newren via GitGitGadget <gitgitgadget@gmail.com>
Date
Dec 4, 2020, 20:47 UTC
Message-ID
<c6e5621c21040d7996551810238921f717400f08.1607114891.git.gitgitgadget@gmail.com>
In-Reply-To
<pull.923.v2.git.git.1607114890.gitgitgadget@gmail.com>
From: Elijah Newren <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 0c37f8bf52..ab3119d2d8 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -196,6 +196,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)
@@ -248,10 +257,19 @@ static int collect_merge_info_callback(int n,
 		newinfo.pathlen = st_add3(newinfo.pathlen, p->pathlen, 1);
 
 		for (i = 0; i < 3; i++) {
-			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);
+			}
 			dirmask >>= 1;
 		}
 
-- 
gitgitgadget
Previous: Elijah Newren via GitGitGadgetNext: Elijah Newren via GitGitGadget
Message 35 of 70 in “fundamentals of merge-ort implementation”
  1. 00/20 fundamentals of merge-ort implementationElijah Newren via GitGitGadget, Nov 29, 2020
  2. 03/20 merge-ort: port merge_start() from merge-recursiveElijah Newren via GitGitGadget, Nov 29, 2020
  3. 02/20 merge-ort: add some high-level algorithm structureElijah Newren via GitGitGadget, Nov 29, 2020
  4. 04/20 merge-ort: use histogram diffElijah Newren via GitGitGadget, Nov 29, 2020
  5. 01/20 merge-ort: setup basic internal data structuresElijah Newren via GitGitGadget, Nov 29, 2020
  6. 07/20 merge-ort: avoid repeating fill_tree_descriptor() on the same treeElijah Newren via GitGitGadget, Nov 29, 2020
  7. 05/20 merge-ort: add an err() function similar to one from merge-recursiveElijah Newren via GitGitGadget, Nov 29, 2020
  8. Ævar Arnfjörð BjarmasonNov 29, 2020
  9. Elijah NewrenNov 30, 2020
  10. Ævar Arnfjörð BjarmasonNov 29, 2020
  11. 10/20 merge-ort: avoid recursing into identical treesElijah Newren via GitGitGadget, Nov 29, 2020
  12. 08/20 merge-ort: compute a few more useful fields for collect_merge_infoElijah Newren via GitGitGadget, Nov 29, 2020
  13. 06/20 merge-ort: implement a very basic collect_merge_info()Elijah Newren via GitGitGadget, Nov 29, 2020
  14. 11/20 merge-ort: add a preliminary simple process_entries() implementationElijah Newren via GitGitGadget, Nov 29, 2020
  15. 12/20 merge-ort: have process_entries operate in a defined orderElijah Newren via GitGitGadget, Nov 29, 2020
  16. 14/20 merge-ort: step 2 of tree writing -- function to create tree objectElijah Newren via GitGitGadget, Nov 29, 2020
  17. 09/20 merge-ort: record stage and auxiliary info for every pathElijah Newren via GitGitGadget, Nov 29, 2020
  18. 15/20 merge-ort: step 3 of tree writing -- handling subdirectories as we goElijah Newren via GitGitGadget, Nov 29, 2020
  19. 16/20 merge-ort: basic outline for merge_switch_to_result()Elijah Newren via GitGitGadget, Nov 29, 2020
  20. 13/20 merge-ort: step 1 of tree writing -- record basenames, modes, and oidsElijah Newren via GitGitGadget, Nov 29, 2020
  21. 19/20 merge-ort: add implementation of record_conflicted_index_entries()Elijah Newren via GitGitGadget, Nov 29, 2020
  22. Ævar Arnfjörð BjarmasonNov 29, 2020
  23. 18/20 tree: enable cmp_cache_name_compare() to be used elsewhereElijah Newren via GitGitGadget, Nov 29, 2020
  24. 17/20 merge-ort: add implementation of checkout()Elijah Newren via GitGitGadget, Nov 29, 2020
  25. 20/20 merge-ort: free data structures in merge_finalize()Elijah Newren via GitGitGadget, Nov 29, 2020
  26. Elijah NewrenNov 29, 2020
  27. 00/20 fundamentals of merge-ort implementationElijah Newren via GitGitGadget, Dec 4, 2020
  28. 02/20 merge-ort: add some high-level algorithm structureElijah Newren via GitGitGadget, Dec 4, 2020
  29. 03/20 merge-ort: port merge_start() from merge-recursiveElijah Newren via GitGitGadget, Dec 4, 2020
  30. 01/20 merge-ort: setup basic internal data structuresElijah Newren via GitGitGadget, Dec 4, 2020
  31. 05/20 merge-ort: add an err() function similar to one from merge-recursiveElijah Newren via GitGitGadget, Dec 4, 2020
  32. 04/20 merge-ort: use histogram diffElijah Newren via GitGitGadget, Dec 4, 2020
  33. 15/20 merge-ort: step 3 of tree writing -- handling subdirectories as we goElijah Newren via GitGitGadget, Dec 4, 2020
  34. 14/20 merge-ort: step 2 of tree writing -- function to create tree objectElijah Newren via GitGitGadget, Dec 4, 2020
  35. 07/20 merge-ort: avoid repeating fill_tree_descriptor() on the same treeElijah Newren via GitGitGadget, Dec 4, 2020
  36. 09/20 merge-ort: record stage and auxiliary info for every pathElijah Newren via GitGitGadget, Dec 4, 2020
  37. 11/20 merge-ort: add a preliminary simple process_entries() implementationElijah Newren via GitGitGadget, Dec 4, 2020
  38. 10/20 merge-ort: avoid recursing into identical treesElijah Newren via GitGitGadget, Dec 4, 2020
  39. 08/20 merge-ort: compute a few more useful fields for collect_merge_infoElijah Newren via GitGitGadget, Dec 4, 2020
  40. 19/20 merge-ort: add implementation of record_conflicted_index_entries()Elijah Newren via GitGitGadget, Dec 4, 2020
  41. 18/20 tree: enable cmp_cache_name_compare() to be used elsewhereElijah Newren via GitGitGadget, Dec 4, 2020
  42. 12/20 merge-ort: have process_entries operate in a defined orderElijah Newren via GitGitGadget, Dec 4, 2020
  43. 13/20 merge-ort: step 1 of tree writing -- record basenames, modes, and oidsElijah Newren via GitGitGadget, Dec 4, 2020
  44. 06/20 merge-ort: implement a very basic collect_merge_info()Elijah Newren via GitGitGadget, Dec 4, 2020
  45. 17/20 merge-ort: add implementation of checkout()Elijah Newren via GitGitGadget, Dec 4, 2020
  46. 16/20 merge-ort: basic outline for merge_switch_to_result()Elijah Newren via GitGitGadget, Dec 4, 2020
  47. 20/20 merge-ort: free data structures in merge_finalize()Elijah Newren via GitGitGadget, Dec 4, 2020
  48. 00/20 fundamentals of merge-ort implementationElijah Newren via GitGitGadget, Dec 13, 2020
  49. 01/20 merge-ort: setup basic internal data structuresElijah Newren via GitGitGadget, Dec 13, 2020
  50. 04/20 merge-ort: use histogram diffElijah Newren via GitGitGadget, Dec 13, 2020
  51. 03/20 merge-ort: port merge_start() from merge-recursiveElijah Newren via GitGitGadget, Dec 13, 2020
  52. 02/20 merge-ort: add some high-level algorithm structureElijah Newren via GitGitGadget, Dec 13, 2020
  53. 08/20 merge-ort: compute a few more useful fields for collect_merge_infoElijah Newren via GitGitGadget, Dec 13, 2020
  54. 06/20 merge-ort: implement a very basic collect_merge_info()Elijah Newren via GitGitGadget, Dec 13, 2020
  55. 07/20 merge-ort: avoid repeating fill_tree_descriptor() on the same treeElijah Newren via GitGitGadget, Dec 13, 2020
  56. 05/20 merge-ort: add an err() function similar to one from merge-recursiveElijah Newren via GitGitGadget, Dec 13, 2020
  57. 10/20 merge-ort: avoid recursing into identical treesElijah Newren via GitGitGadget, Dec 13, 2020
  58. 14/20 merge-ort: step 2 of tree writing -- function to create tree objectElijah Newren via GitGitGadget, Dec 13, 2020
  59. 12/20 merge-ort: have process_entries operate in a defined orderElijah Newren via GitGitGadget, Dec 13, 2020
  60. 16/20 merge-ort: basic outline for merge_switch_to_result()Elijah Newren via GitGitGadget, Dec 13, 2020
  61. 09/20 merge-ort: record stage and auxiliary info for every pathElijah Newren via GitGitGadget, Dec 13, 2020
  62. 18/20 tree: enable cmp_cache_name_compare() to be used elsewhereElijah Newren via GitGitGadget, Dec 13, 2020
  63. 15/20 merge-ort: step 3 of tree writing -- handling subdirectories as we goElijah Newren via GitGitGadget, Dec 13, 2020
  64. 17/20 merge-ort: add implementation of checkout()Elijah Newren via GitGitGadget, Dec 13, 2020
  65. 19/20 merge-ort: add implementation of record_conflicted_index_entries()Elijah Newren via GitGitGadget, Dec 13, 2020
  66. 20/20 merge-ort: free data structures in merge_finalize()Elijah Newren via GitGitGadget, Dec 13, 2020
  67. 13/20 merge-ort: step 1 of tree writing -- record basenames, modes, and oidsElijah Newren via GitGitGadget, Dec 13, 2020
  68. 11/20 merge-ort: add a preliminary simple process_entries() implementationElijah Newren via GitGitGadget, Dec 13, 2020
  69. Felipe ContrerasDec 14, 2020
  70. Elijah NewrenDec 14, 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.