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

[PATCH v2 4/4] Bump rename limit defaults (yet again)

From
Elijah Newren via GitGitGadget <gitgitgadget@gmail.com>
Date
Jul 14, 2021, 01:12 UTC
Message-ID
<8f1deb6dd16a0c0d88cf594d2019b3096dbe5383.1626225154.git.gitgitgadget@gmail.com>
In-Reply-To
<pull.1044.v2.git.git.1626225153.gitgitgadget@gmail.com>
From: Elijah Newren <newren@gmail.com>

These were last bumped in commit 92c57e5c1d29 (bump rename limit defaults (again), 2011-02-19), and were bumped both because processors had gotten faster, and because people were getting ugly merges that caused problems and reporting it to the mailing list (suggesting that folks were willing to spend more time waiting).

Since that time:
  * Linus has continued recommending kernel folks to set
    diff.renameLimit=0 (maps to 32767, currently)
  * Folks with repositories with lots of renames were happy to set
    merge.renameLimit above 32767, once the code supported that, to
    get correct cherry-picks
  * Processors have gotten faster
  * It has been discovered that the timing methodology used last time
    probably used too large example files.
The last point is probably worth explaining a bit more:
  * The "average" file size used appears to have been average blob size
    in the linux kernel history at the time (probably v2.6.25 or
    something close to it).
  * Since bigger files are modified more frequently, such a computation
    weights towards larger files.
  * Larger files may be more likely to be modified over time, but are
    not more likely to be renamed -- the mean and median blob size
    within a tree are a bit higher than the mean and median of blob
    sizes in the history leading up to that version for the linux
    kernel.
  * The mean blob size in v2.6.25 was half the average blob size in
    history leading to that point
  * The median blob size in v2.6.25 was about 40% of the mean blob size
    in v2.6.25.
  * Since the mean blob size is more than double the median blob size,
    any file as big as the mean will not be compared to any files of
    median size or less (because they'd be more than 50% dissimilar).
  * Since it is the number of files compared that provides the O(n^2)
    behavior, median-sized files should matter more than mean-sized
    ones.

The combined effect of the above is that the file size used in past calculations was likely about 5x too large. Combine that with a CPU performance improvement of ~30%, and we can increase the limits by a factor of sqrt(5/(1-.3)) = 2.67, while keeping the original stated time limits.

Keeping the same approximate time limit probably makes sense for diff.renameLimit (there is no progress feedback in e.g. git log -p), but the experience above suggests merge.renameLimit could be extended significantly. In fact, it probably would make sense to have an unlimited default setting for merge.renameLimit, but that would likely need to be coupled with changes to how progress is displayed. (See https://lore.kernel.org/git/YOx+Ok%2FEYvLqRMzJ@coredump.intra.peff.net/ for details in that area.) For now, let's just bump the approximate time limit from 10s to 1m.

(Note: We do not want to use actual time limits, because getting results that depend on how loaded your system is that day feels bad, and because we don't discover that we won't get all the renames until after we've put in a lot of work rather than just upfront telling the user there are too many files involved.)

Using the original time limit of 2s for diff.renameLimit, and bumping merge.renameLimit from 10s to 60s, I found the following timings using the simple script at the end of this commit message (on an AWS c5.xlarge which reports as "Intel(R) Xeon(R) Platinum 8124M CPU @ 3.00GHz"):

      N   Timing
   1300    1.995s
   7100   59.973s

So let's round down to nice even numbers and bump the limits from 400->1000, and from 1000->7000.

Here is the measure_rename_perf script (adapted from https://lore.kernel.org/git/20080211113516.GB6344@coredump.intra.peff.net/ in particular to avoid triggering the linear handling from basename-guided rename detection):

    #!/bin/bash
    n=$1; shift
    rm -rf repo
    mkdir repo && cd repo
    git init -q -b main
    mkdata() {
      mkdir $1
      for i in `seq 1 $2`; do
        (sed "s/^/$i /" <../sample
         echo tag: $1
        ) >$1/$i
      done
    }
    mkdata initial $n
    git add .
    git commit -q -m initial
    mkdata new $n
    git add .
    cd new
    for i in *; do git mv $i $i.renamed; done
    cd ..
    git rm -q -rf initial
    git commit -q -m new
    time git diff-tree -M -l0 --summary HEAD^ HEAD
Signed-off-by: Elijah Newren <newren@gmail.com>
---
 Documentation/config/diff.txt  | 2 +-
 Documentation/config/merge.txt | 2 +-
 diff.c                         | 2 +-
 merge-ort.c                    | 2 +-
 merge-recursive.c              | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/Documentation/config/diff.txt b/Documentation/config/diff.txt
index e26a63d0d42..167c479f376 100644
--- a/Documentation/config/diff.txt
+++ b/Documentation/config/diff.txt
@@ -120,7 +120,7 @@ diff.orderFile::
 diff.renameLimit::
 	The number of files to consider in the exhaustive portion of
 	copy/rename detection; equivalent to the 'git diff' option
-	`-l`.  If not set, the default value is 400.  This setting has
+	`-l`.  If not set, the default value is 1000.  This setting has
 	no effect if rename detection is turned off.
 
 diff.renames::
diff --git a/Documentation/config/merge.txt b/Documentation/config/merge.txt
index aca0c92dbe6..101eabb3f0c 100644
--- a/Documentation/config/merge.txt
+++ b/Documentation/config/merge.txt
@@ -37,7 +37,7 @@ merge.renameLimit::
 	rename detection during a merge.  If not specified, defaults
 	to the value of diff.renameLimit.  If neither
 	merge.renameLimit nor diff.renameLimit are specified, defaults
-	to 1000.  This setting has no effect if rename detection is
+	to 7000.  This setting has no effect if rename detection is
 	turned off.
 
 merge.renames::
diff --git a/diff.c b/diff.c
index 2454e34cf6d..0244a371d32 100644
--- a/diff.c
+++ b/diff.c
@@ -35,7 +35,7 @@
 
 static int diff_detect_rename_default;
 static int diff_indent_heuristic = 1;
-static int diff_rename_limit_default = 400;
+static int diff_rename_limit_default = 1000;
 static int diff_suppress_blank_empty;
 static int diff_use_color_default = -1;
 static int diff_color_moved_default;
diff --git a/merge-ort.c b/merge-ort.c
index b954f7184a5..8a84375e940 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -2558,7 +2558,7 @@ static void detect_regular_renames(struct merge_options *opt,
 	diff_opts.detect_rename = DIFF_DETECT_RENAME;
 	diff_opts.rename_limit = opt->rename_limit;
 	if (opt->rename_limit <= 0)
-		diff_opts.rename_limit = 1000;
+		diff_opts.rename_limit = 7000;
 	diff_opts.rename_score = opt->rename_score;
 	diff_opts.show_rename_progress = opt->show_rename_progress;
 	diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT;
diff --git a/merge-recursive.c b/merge-recursive.c
index 4327e0cfa33..f19f8cc37bd 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -1879,7 +1879,7 @@ static struct diff_queue_struct *get_diffpairs(struct merge_options *opt,
 	 */
 	if (opts.detect_rename > DIFF_DETECT_RENAME)
 		opts.detect_rename = DIFF_DETECT_RENAME;
-	opts.rename_limit = (opt->rename_limit >= 0) ? opt->rename_limit : 1000;
+	opts.rename_limit = (opt->rename_limit >= 0) ? opt->rename_limit : 7000;
 	opts.rename_score = opt->rename_score;
 	opts.show_rename_progress = opt->show_rename_progress;
 	opts.output_format = DIFF_FORMAT_NO_OUTPUT;
-- 
gitgitgadget
Previous: Elijah NewrenNext: Jeff King
Message 31 of 44 in “Improve the documentation and warnings dealing with rename/copy limits”
  1. 0/3 Improve the documentation and warnings dealing with rename/copy limitsElijah Newren via GitGitGadget, Jul 11, 2021
  2. 2/3 doc: document the special handling of -l0Elijah Newren via GitGitGadget, Jul 11, 2021
  3. Eric SunshineJul 11, 2021
  4. Elijah NewrenJul 11, 2021
  5. 1/3 doc: clarify documentation for rename/copy limitsElijah Newren via GitGitGadget, Jul 11, 2021
  6. Bagas SanjayaJul 11, 2021
  7. Elijah NewrenJul 11, 2021
  8. Derrick StoleeJul 12, 2021
  9. Junio C HamanoJul 12, 2021
  10. 3/3 diff: correct warning message when renameLimit exceededElijah Newren via GitGitGadget, Jul 11, 2021
  11. Derrick StoleeJul 12, 2021
  12. Elijah NewrenJul 12, 2021
  13. Junio C HamanoJul 14, 2021
  14. Elijah NewrenJul 14, 2021
  15. Junio C HamanoJul 14, 2021
  16. Elijah NewrenJul 14, 2021
  17. Junio C HamanoJul 14, 2021
  18. Elijah NewrenJul 14, 2021
  19. 0/4 Rename/copy limits -- docs, warnings, and new defaultsElijah Newren via GitGitGadget, Jul 14, 2021
  20. 1/4 diff: correct warning message when renameLimit exceededElijah Newren via GitGitGadget, Jul 14, 2021
  21. 2/4 doc: clarify documentation for rename/copy limitsElijah Newren via GitGitGadget, Jul 14, 2021
  22. Ævar Arnfjörð BjarmasonJul 14, 2021
  23. Elijah NewrenJul 14, 2021
  24. Ævar Arnfjörð BjarmasonJul 14, 2021
  25. Elijah NewrenJul 14, 2021
  26. 3/4 doc: document the special handling of -l0Elijah Newren via GitGitGadget, Jul 14, 2021
  27. Jeff KingJul 14, 2021
  28. Elijah NewrenJul 14, 2021
  29. Jeff KingJul 14, 2021
  30. Elijah NewrenJul 14, 2021
  31. 4/4 Bump rename limit defaults (yet again)Elijah Newren via GitGitGadget, Jul 14, 2021
  32. Jeff KingJul 14, 2021
  33. Elijah NewrenJul 14, 2021
  34. Jeff KingJul 14, 2021
  35. Elijah NewrenJul 14, 2021
  36. Jeff KingJul 14, 2021
  37. 0/4 Rename/copy limits -- docs, warnings, and new defaultsElijah Newren via GitGitGadget, Jul 15, 2021
  38. 1/4 diff: correct warning message when renameLimit exceededElijah Newren via GitGitGadget, Jul 15, 2021
  39. 2/4 doc: clarify documentation for rename/copy limitsElijah Newren via GitGitGadget, Jul 15, 2021
  40. 3/4 diffcore-rename: treat a rename_limit of 0 as unlimitedElijah Newren via GitGitGadget, Jul 15, 2021
  41. Junio C HamanoJul 15, 2021
  42. 4/4 Bump rename limit defaults (yet again)Elijah Newren via GitGitGadget, Jul 15, 2021
  43. Derrick StoleeJul 15, 2021
  44. Junio C HamanoJul 15, 2021

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.