mirror of
https://github.com/github/semantic.git
synced 2024-12-27 00:44:57 +03:00
µ-optimizations for SES.
1. Avoid redundant computations of cost on the fast path (equal elements at this vertex). 2. Don’t call `min`; inline the branches instead. 3. Don’t call `costOfStream`; inline the costs instead.
This commit is contained in:
parent
5253de2ef5
commit
dac24bbf24
@ -34,18 +34,38 @@ public func SES<Leaf, Annotation, C: CollectionType>(a: C, _ b: C, cost: Free<Le
|
|||||||
|
|
||||||
if let diagonal = diagonal, right = right, down = down {
|
if let diagonal = diagonal, right = right, down = down {
|
||||||
let here = recur(a[i], b[j])
|
let here = recur(a[i], b[j])
|
||||||
// If the diff at this vertex is zero-cost, we’re not going to find a cheaper one either rightwards or downwards. We can therefore short-circuit selecting the best outgoing edge and save ourselves evaluating the entire row rightwards and the entire column downwards from this point.
|
if let diagonalDiff = here {
|
||||||
//
|
let hereCost = cost(diagonalDiff)
|
||||||
// Thus, in the best case (two equal sequences), we now complete in O(n + m). However, this optimization only applies to equalities at the beginning of the edit graph; once inequalities are encountered, the remainder of the diff is effectively O(nm).
|
let diagonalCost = hereCost + (diagonal.value.first?.1 ?? 0)
|
||||||
if let here = here where cost(here) == 0 { return cons(here, rest: diagonal) }
|
// If the diff at this vertex is zero-cost, we’re not going to find a cheaper one either rightwards or downwards. We can therefore short-circuit selecting the best outgoing edge and save ourselves evaluating the entire row rightwards and the entire column downwards from this point.
|
||||||
let right = (right, Diff.Delete(a[i]), costOfStream(right))
|
//
|
||||||
let down = (down, Diff.Insert(b[j]), costOfStream(down))
|
// Thus, in the best case (two equal sequences), we now complete in O(n + m). However, this optimization only applies to equalities at the beginning of the edit graph; once inequalities are encountered, the remainder of the diff is effectively O(nm).
|
||||||
let diagonal = here.map { (diagonal, $0, costOfStream(diagonal)) }
|
guard hereCost != 0 else { return .Cons((diagonalDiff, diagonalCost), diagonal) }
|
||||||
// nominate the best edge to continue along, not considering diagonal if `recur` returned `nil`.
|
|
||||||
let (best, diff, _) = diagonal
|
let rightDiff = Diff.Delete(a[i])
|
||||||
.map { min($0, right, down) { $0.2 < $1.2 } }
|
let rightCost = cost(rightDiff) + (right.value.first?.1 ?? 0)
|
||||||
?? min(right, down) { $0.2 < $1.2 }
|
let downDiff = Diff.Insert(b[j])
|
||||||
return cons(diff, rest: best)
|
let downCost = cost(downDiff) + (down.value.first?.1 ?? 0)
|
||||||
|
|
||||||
|
if rightCost < downCost && rightCost < diagonalCost {
|
||||||
|
return .Cons((rightDiff, rightCost), right)
|
||||||
|
} else if downCost < diagonalCost {
|
||||||
|
return .Cons((downDiff, downCost), down)
|
||||||
|
} else {
|
||||||
|
return .Cons((diagonalDiff, diagonalCost), diagonal)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let rightDiff = Diff.Delete(a[i])
|
||||||
|
let rightCost = cost(rightDiff) + (right.value.first?.1 ?? 0)
|
||||||
|
let downDiff = Diff.Insert(b[j])
|
||||||
|
let downCost = cost(downDiff) + (down.value.first?.1 ?? 0)
|
||||||
|
|
||||||
|
if rightCost < downCost {
|
||||||
|
return .Cons((rightDiff, rightCost), right)
|
||||||
|
} else {
|
||||||
|
return .Cons((downDiff, downCost), down)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// right extent of the edit graph; can only move down
|
// right extent of the edit graph; can only move down
|
||||||
|
Loading…
Reference in New Issue
Block a user