summaryrefslogtreecommitdiff
path: root/xdiff
diff options
context:
space:
mode:
authorDavide Libenzi <davidel@xmailserver.org>2008-11-07 21:24:33 -0800
committerJunio C Hamano <gitster@pobox.com>2008-12-02 23:45:37 -0800
commit733070bea9ce28d557f0b0950acc05b3fe6ff6c6 (patch)
tree4bfc97b38f65e30f28ac296a392d1cf85b36313a /xdiff
parent0fd9d7e66deb7071da2a568b96c94f94ee890908 (diff)
downloadgit-733070bea9ce28d557f0b0950acc05b3fe6ff6c6.tar.gz
xdiff: give up scanning similar lines early
In a corner case of large files whose lines do not match uniquely, the loop to eliminate a line that matches multiple locations adjacent to a run of lines that do not uniquely match wasted too much cycles. Fix this by giving up early after scanning 100 lines in both direction. Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'xdiff')
-rw-r--r--xdiff/xprepare.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/xdiff/xprepare.c b/xdiff/xprepare.c
index e87ab57c65..a43aa72cd0 100644
--- a/xdiff/xprepare.c
+++ b/xdiff/xprepare.c
@@ -23,10 +23,9 @@
#include "xinclude.h"
-
#define XDL_KPDIS_RUN 4
#define XDL_MAX_EQLIMIT 1024
-
+#define XDL_SIMSCAN_WINDOW 100
typedef struct s_xdlclass {
@@ -313,6 +312,18 @@ static int xdl_clean_mmatch(char const *dis, long i, long s, long e) {
long r, rdis0, rpdis0, rdis1, rpdis1;
/*
+ * Limits the window the is examined during the similar-lines
+ * scan. The loops below stops when dis[i - r] == 1 (line that
+ * has no match), but there are corner cases where the loop
+ * proceed all the way to the extremities by causing huge
+ * performance penalties in case of big files.
+ */
+ if (i - s > XDL_SIMSCAN_WINDOW)
+ s = i - XDL_SIMSCAN_WINDOW;
+ if (e - i > XDL_SIMSCAN_WINDOW)
+ e = i + XDL_SIMSCAN_WINDOW;
+
+ /*
* Scans the lines before 'i' to find a run of lines that either
* have no match (dis[j] == 0) or have multiple matches (dis[j] > 1).
* Note that we always call this function with dis[i] > 1, so the