diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/BKTree.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/BKTree.cs index de49f93971eb8..367d486e13597 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/BKTree.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/BKTree.cs @@ -107,33 +107,48 @@ private void Lookup( return; } - // We always want to compute the real edit distance (ignoring any thresholds). This is - // because we need that edit distance to appropriately determine which edges to walk + // We may need to compute the real edit distance (ignoring any thresholds) in the case + // where edges exist as we need that edit distance to appropriately determine which edges to walk // in the tree. var characterSpan = currentNode.WordSpan; + + // The GetEditDistance call below serves two purposes: + // 1) To determine whether currentNode should be added to the result + // 2) To determine whether children need to be searched + // + // If there are no edges, we don't need the information to determine case 2. So, as a + // performance optimization, in that case we send in a threshold to GetEditDistance + // that indicates only the work necessary to determine case 1 need be performed. + var edgesExist = currentNode.EdgeCount > 0; var editDistance = EditDistance.GetEditDistance( _concatenatedLowerCaseWords.AsSpan(characterSpan.Start, characterSpan.Length), - queryCharacters.AsSpan(0, queryLength)); + queryCharacters.AsSpan(0, queryLength), + edgesExist ? int.MaxValue : threshold); + // Case 1 if (editDistance <= threshold) { // Found a match. result.Add(new string(_concatenatedLowerCaseWords, characterSpan.Start, characterSpan.Length)); } - var min = editDistance - threshold; - var max = editDistance + threshold; - - var startInclusive = currentNode.FirstEdgeIndex; - var endExclusive = startInclusive + currentNode.EdgeCount; - for (var i = startInclusive; i < endExclusive; i++) + // Case 2 + if (edgesExist) { - var childEditDistance = _edges[i].EditDistance; - if (min <= childEditDistance && childEditDistance <= max) + var min = editDistance - threshold; + var max = editDistance + threshold; + + var startInclusive = currentNode.FirstEdgeIndex; + var endExclusive = startInclusive + currentNode.EdgeCount; + for (var i = startInclusive; i < endExclusive; i++) { - Lookup(_nodes[_edges[i].ChildNodeIndex], - queryCharacters, queryLength, threshold, ref result, - recursionCount + 1); + var childEditDistance = _edges[i].EditDistance; + if (min <= childEditDistance && childEditDistance <= max) + { + Lookup(_nodes[_edges[i].ChildNodeIndex], + queryCharacters, queryLength, threshold, ref result, + recursionCount + 1); + } } } }