Improve merge performance by avoiding in-index merges.
In the early days of Git we performed a 3-way read-tree based merge before attempting any specific merge strategy, as our core merge strategies of merge-one-file and merge-recursive were slower script based programs which took far longer to execute. This was a good performance optimization in the past, as most merges were able to be handled strictly by `read-tree -m -u`. However now that merge-recursive is a C based program which performs a full 3-way read-tree before it starts running we need to pay the cost of the 3-way read-tree twice if we have to do any sort of file level merging. This slows down some classes of simple merges which `read-tree -m -u` could not handle but which merge-recursive does automatically. For a really trivial merge which can be handled entirely by `read-tree -m -u`, skipping the read-tree and just going directly into merge-recursive saves on average 50 ms on my PowerPC G4 system. May sound odd, but it does appear to be true. In a really simple merge which needs to use merge-recursive to handle a file that was modified on both branches, skipping the read-tree in git-merge saves on average almost 100 ms (on the same PowerPC G4) as we avoid doing some work twice. We only avoid `read-tree -m -u` if the only strategy to use is merge-recursive, as not all merge strategies perform as well as merge-recursive does. Signed-off-by: Shawn O. Pearce <spearce@spearce.org> Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:

committed by
Junio C Hamano

parent
2a3a3c247e
commit
c82d7117a1
40
git-merge.sh
40
git-merge.sh
@ -298,24 +298,30 @@ f,*)
|
|||||||
;;
|
;;
|
||||||
?,1,*,)
|
?,1,*,)
|
||||||
# We are not doing octopus, not fast forward, and have only
|
# We are not doing octopus, not fast forward, and have only
|
||||||
# one common. See if it is really trivial.
|
# one common.
|
||||||
git var GIT_COMMITTER_IDENT >/dev/null || exit
|
|
||||||
|
|
||||||
echo "Trying really trivial in-index merge..."
|
|
||||||
git-update-index --refresh 2>/dev/null
|
git-update-index --refresh 2>/dev/null
|
||||||
if git-read-tree --trivial -m -u -v $common $head "$1" &&
|
case " $use_strategies " in
|
||||||
result_tree=$(git-write-tree)
|
*' recursive '*|*' recur '*)
|
||||||
then
|
: run merge later
|
||||||
echo "Wonderful."
|
;;
|
||||||
result_commit=$(
|
*)
|
||||||
echo "$merge_msg" |
|
# See if it is really trivial.
|
||||||
git-commit-tree $result_tree -p HEAD -p "$1"
|
git var GIT_COMMITTER_IDENT >/dev/null || exit
|
||||||
) || exit
|
echo "Trying really trivial in-index merge..."
|
||||||
finish "$result_commit" "In-index merge"
|
if git-read-tree --trivial -m -u -v $common $head "$1" &&
|
||||||
dropsave
|
result_tree=$(git-write-tree)
|
||||||
exit 0
|
then
|
||||||
fi
|
echo "Wonderful."
|
||||||
echo "Nope."
|
result_commit=$(
|
||||||
|
echo "$merge_msg" |
|
||||||
|
git-commit-tree $result_tree -p HEAD -p "$1"
|
||||||
|
) || exit
|
||||||
|
finish "$result_commit" "In-index merge"
|
||||||
|
dropsave
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "Nope."
|
||||||
|
esac
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
# An octopus. If we can reach all the remote we are up to date.
|
# An octopus. If we can reach all the remote we are up to date.
|
||||||
|
Reference in New Issue
Block a user