From d90cd6de7716644e5ec5c6d91cea25eeb88aae3e Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Mon, 17 Jul 2017 13:30:11 +0200 Subject: [PATCH] Refactor find_diff_rec and detect kept prefix/suffixes early Certain cases, like diffing an empty buffer with a big buffer, were very slow, now this should get better as we will directly detect the matching eol at the end of both buffers, end then immediatly detect we need to add the rest of the big buffer. We still are too slow on some general diff when there is a lot of differences. --- src/diff.hh | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/diff.hh b/src/diff.hh index 3535dadc..306ed301 100644 --- a/src/diff.hh +++ b/src/diff.hh @@ -96,6 +96,9 @@ struct Diff inline void append_diff(Vector& diffs, Diff diff) { + if (diff.len == 0) + return; + if (not diffs.empty() and diffs.back().mode == diff.mode and (diff.mode != Diff::Add or diffs.back().posB + diffs.back().len == diff.posB)) @@ -109,7 +112,21 @@ void find_diff_rec(Iterator a, int offA, int lenA, Iterator b, int offB, int lenB, int* V1, int* V2, Equal eq, Vector& diffs) { - if (lenA > 0 and lenB > 0) + int prefix_len = 0; + while (lenA > 0 and lenB > 0 and a[offA] == b[offB]) + ++offA, ++offB, --lenA, --lenB, ++prefix_len; + + int suffix_len = 0; + while (lenA != 0 and lenB != 0 and a[offA + lenA - 1] == b[offB + lenB - 1]) + --lenA, --lenB, ++suffix_len; + + append_diff(diffs, {Diff::Keep, prefix_len, 0}); + + if (lenA == 0) + append_diff(diffs, {Diff::Add, lenB, offB}); + else if (lenB == 0) + append_diff(diffs, {Diff::Remove, lenA, 0}); + else { auto middle_snake = find_middle_snake(a + offA, lenA, b + offB, lenB, V1, V2, eq); kak_assert(middle_snake.u <= lenA and middle_snake.v <= lenB); @@ -119,8 +136,7 @@ void find_diff_rec(Iterator a, int offA, int lenA, b, offB, middle_snake.y, V1, V2, eq, diffs); - if (int len = middle_snake.u - middle_snake.x) - append_diff(diffs, {Diff::Keep, len, 0}); + append_diff(diffs, {Diff::Keep, middle_snake.u - middle_snake.x, 0}); find_diff_rec(a, offA + middle_snake.u, lenA - middle_snake.u, b, offB + middle_snake.v, lenB - middle_snake.v, @@ -131,22 +147,18 @@ void find_diff_rec(Iterator a, int offA, int lenA, if (middle_snake.d == 1) { const int diag = middle_snake.x - (middle_snake.add ? 0 : 1); - if (diag != 0) - append_diff(diffs, {Diff::Keep, diag, 0}); + append_diff(diffs, {Diff::Keep, diag, 0}); if (middle_snake.add) append_diff(diffs, {Diff::Add, 1, offB + diag}); else append_diff(diffs, {Diff::Remove, 1, 0}); } - if (int len = middle_snake.u - middle_snake.x) - append_diff(diffs, {Diff::Keep, len, 0}); + append_diff(diffs, {Diff::Keep, middle_snake.u - middle_snake.x, 0}); } } - else if (lenB > 0) - append_diff(diffs, {Diff::Add, lenB, offB}); - else if (lenA > 0) - append_diff(diffs, {Diff::Remove, lenA, 0}); + + append_diff(diffs, {Diff::Keep, suffix_len, 0}); } template::value_type>>