From a3718cde0662d110cb989d358924ce0f5919ae25 Mon Sep 17 00:00:00 2001 From: "Jonah H. Harris" Date: Tue, 2 Feb 2021 03:57:12 -0500 Subject: [PATCH] Optimizing sorted GEORADIUS COUNT with partial sorting. (#8326) This commit provides an optimization, in terms of time, for all GEORADIUS* and GEOSEARCH* searches which utilize the default, sorted, COUNT clause. This is commonly used for nearest-neighbor (top-K points closest to a given lat/lon) searches. While the previous implementation appends all matching points to the geoPoint array and performs pruning after-the-fact via a full sort and [0, count)-based for-loop, this PR sorts only the required number of elements. This optimization provides a 5-20% improvement in runtime depending on the density of points of interest (POI) as well as the radius searched. No performance degradation has been observed. --- src/geo.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/geo.c b/src/geo.c index 9c668288b..b2009b516 100644 --- a/src/geo.c +++ b/src/geo.c @@ -31,6 +31,7 @@ #include "geo.h" #include "geohash_helper.h" #include "debugmacro.h" +#include "pqsort.h" /* Things exported from t_zset.c only for geo.c, since it is the only other * part of Redis that requires close zset introspection. */ @@ -699,10 +700,20 @@ void georadiusGeneric(client *c, int srcKeyIndex, int flags) { long option_length = 0; /* Process [optional] requested sorting */ - if (sort == SORT_ASC) { - qsort(ga->array, result_length, sizeof(geoPoint), sort_gp_asc); - } else if (sort == SORT_DESC) { - qsort(ga->array, result_length, sizeof(geoPoint), sort_gp_desc); + if (sort != SORT_NONE) { + int (*sort_gp_callback)(const void *a, const void *b) = NULL; + if (sort == SORT_ASC) { + sort_gp_callback = sort_gp_asc; + } else if (sort == SORT_DESC) { + sort_gp_callback = sort_gp_desc; + } + + if (returned_items == result_length) { + qsort(ga->array, result_length, sizeof(geoPoint), sort_gp_callback); + } else { + pqsort(ga->array, result_length, sizeof(geoPoint), sort_gp_callback, + 0, (returned_items - 1)); + } } if (storekey == NULL) {