From ee1b3b1f8bf88fe82f3c97ed6b48c996352d0748 Mon Sep 17 00:00:00 2001 From: Vladimir Agafonkin Date: Wed, 25 Mar 2020 14:04:53 +0200 Subject: [PATCH] optimize tail calls in feature state sorting --- src/data/feature_position_map.js | 40 ++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/src/data/feature_position_map.js b/src/data/feature_position_map.js index 72bafce0058..15137377a39 100644 --- a/src/data/feature_position_map.js +++ b/src/data/feature_position_map.js @@ -95,25 +95,31 @@ function getNumericId(value: mixed) { } // custom quicksort that sorts ids, indices and offsets together (by ids) +// uses Hoare partitioning & manual tail call optimization to avoid worst case scenarios function sort(ids, positions, left, right) { - if (left >= right) return; - - const pivot = ids[(left + right) >> 1]; - let i = left - 1; - let j = right + 1; - - while (true) { - do i++; while (ids[i] < pivot); - do j--; while (ids[j] > pivot); - if (i >= j) break; - swap(ids, i, j); - swap(positions, 3 * i, 3 * j); - swap(positions, 3 * i + 1, 3 * j + 1); - swap(positions, 3 * i + 2, 3 * j + 2); - } + while (left < right) { + const pivot = ids[(left + right) >> 1]; + let i = left - 1; + let j = right + 1; + + while (true) { + do i++; while (ids[i] < pivot); + do j--; while (ids[j] > pivot); + if (i >= j) break; + swap(ids, i, j); + swap(positions, 3 * i, 3 * j); + swap(positions, 3 * i + 1, 3 * j + 1); + swap(positions, 3 * i + 2, 3 * j + 2); + } - sort(ids, positions, left, j); - sort(ids, positions, j + 1, right); + if (j - left < right - j) { + sort(ids, positions, left, j); + left = j + 1; + } else { + sort(ids, positions, j + 1, right); + right = j; + } + } } function swap(arr, i, j) {