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

[PATCH v2] xdiff: optimize patience diff's LCS search

From
YGYee Cheng Chin via GitGitGadget <gitgitgadget@gmail.com>
Date
Nov 27, 2025, 02:16 UTC
Message-ID
<pull.2109.v2.git.git.1764209766305.gitgitgadget@gmail.com>
In-Reply-To
<pull.2109.git.git.1764152756908.gitgitgadget@gmail.com>
From: Yee Cheng Chin <ychin.git@gmail.com>

The find_longest_common_sequence() function in patience diff is inefficient as it calls binary_search() for every unique line it encounters when deciding where to put it in the sequence. From instrumentation (using xctrace) on popular repositories, binary_search() takes up 50-60% of the run time within patience_diff() when performing a diff.

To optimize this, add a boundary condition check before binary_search() is called to see if the encountered unique line is located after the entire currently tracked longest subsequence. If so, skip the unnecessary binary search and simply append the entry to the end of sequence. Given that most files compared in a diff are usually quite similar to each other, this condition is very common, and should be hit much more frequently than the binary search.

Below are some end-to-end performance results by timing `git log --shortstat --oneline -500 --patience` on different repositories with the old and new code. Generally speaking this seems to give at least 8-10% speed up. The "binary search hit %" column describes how often the algorithm enters the binary search path instead of the new faster path. Even in the WebKit case we can see that it's quite rare (1.46%).

| Repo     | Speed difference | binary search hit % |
|----------|------------------|---------------------|
| vim      | 1.27x            | 0.01%               |
| pytorch  | 1.16x            | 0.02%               |
| cpython  | 1.14x            | 0.06%               |
| ripgrep  | 1.14x            | 0.03%               |
| git      | 1.13x            | 0.12%               |
| vscode   | 1.09x            | 0.10%               |
| WebKit   | 1.08x            | 1.46%               |

The benchmarks were done using hyperfine, on an Apple M1 Max laptop, with git compiled with `-O3 -flto`.

Signed-off-by: Yee Cheng Chin <ychin.git@gmail.com>
---
    xdiff: optimize patience diff's LCS search
    
    Changes since v1:
    
     * Fix typo in commit message for "pytortch"
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-2109%2Fychin%2Fpatience-optimizations-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-2109/ychin/patience-optimizations-v2
Pull-Request: https://github.com/git/git/pull/2109
Range-diff vs v1:
 1:  dc6d509b59 ! 1:  0f8a2dd719 xdiff: optimize patience diff's LCS search
     @@ Commit message
          | Repo     | Speed difference | binary search hit % |
          |----------|------------------|---------------------|
          | vim      | 1.27x            | 0.01%               |
     -    | pytortch | 1.16x            | 0.02%               |
     +    | pytorch  | 1.16x            | 0.02%               |
          | cpython  | 1.14x            | 0.06%               |
          | ripgrep  | 1.14x            | 0.03%               |
          | git      | 1.13x            | 0.12%               |
 xdiff/xpatience.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/xdiff/xpatience.c b/xdiff/xpatience.c
index 669b653580..13ab0d591c 100644
--- a/xdiff/xpatience.c
+++ b/xdiff/xpatience.c
@@ -211,7 +211,10 @@ static int find_longest_common_sequence(struct hashmap *map, struct entry **res)
 	for (entry = map->first; entry; entry = entry->next) {
 		if (!entry->line2 || entry->line2 == NON_UNIQUE)
 			continue;
-		i = binary_search(sequence, longest, entry);
+		if (longest == 0 || entry->line2 > sequence[longest - 1]->line2)
+			i = longest - 1;
+		else
+			i = binary_search(sequence, longest, entry);
 		entry->previous = i < 0 ? NULL : sequence[i];
 		++i;
 		if (i <= anchor_i)

base-commit: 6ab38b7e9cc7adafc304f3204616a4debd49c6e9
-- 
gitgitgadget
Previous: Yee Cheng Chin
Message 4 of 4 in “xdiff: optimize patience diff's LCS search”
  1. xdiff: optimize patience diff's LCS searchYee Cheng Chin via GitGitGadget, Nov 26, 2025
  2. Junio C HamanoNov 26, 2025
  3. Yee Cheng ChinNov 26, 2025
  4. xdiff: optimize patience diff's LCS searchYee Cheng Chin via GitGitGadget, Nov 27, 2025

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.