Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 782ad9e

Browse files
Andrey M. BorodinCommitfest Bot
Andrey M. Borodin
authored and
Commitfest Bot
committed
Specialize intarray sorting
There is at least one report in the field of storing millions of integers in arrays, so it seems like a good time to specialize intarray's qsort function. In doing so, streamline the comparators: Previously there were three, two for each direction for sorting and one passed to qunique_arg. To preserve the early exit in the case of descending input, pass the direction as an argument to the comparator. This requires giving up duplicate detection, which previously allowed skipping the unique-ifying step. Testing showed no regressions in always calling qunique(). In passing, get rid of nearby checks that the input has at least two elements, since preserving them would make some macros less readable. These are not necessary for correctness, and seem like premature optimizations. Author: Andrey M. Borodin <x4mmm@yandex-team.ru> Discussion: https://postgr.es/m/098A3E67-E4A6-4086-9C66-B1EAEB1DFE1C@yandex-team.ru
1 parent fc069a3 commit 782ad9e

File tree

2 files changed

+34
-48
lines changed

2 files changed

+34
-48
lines changed

contrib/intarray/_int.h

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,17 @@ typedef struct
4141
#define SORT(x) \
4242
do { \
4343
int _nelems_ = ARRNELEMS(x); \
44-
if (_nelems_ > 1) \
45-
isort(ARRPTR(x), _nelems_); \
44+
bool _asc = true; \
45+
isort(ARRPTR(x), _nelems_, &_asc); \
4646
} while(0)
4747

4848
/* sort the elements of the array and remove duplicates */
4949
#define PREPAREARR(x) \
5050
do { \
5151
int _nelems_ = ARRNELEMS(x); \
52-
if (_nelems_ > 1) \
53-
if (isort(ARRPTR(x), _nelems_)) \
54-
(x) = _int_unique(x); \
52+
bool _asc = true; \
53+
isort(ARRPTR(x), _nelems_, &_asc); \
54+
(x) = _int_unique(x); \
5555
} while(0)
5656

5757
/* "wish" function */
@@ -109,7 +109,7 @@ typedef struct
109109
/*
110110
* useful functions
111111
*/
112-
bool isort(int32 *a, int len);
112+
void isort(int32 *a, size_t len, void *arg);
113113
ArrayType *new_intArrayType(int num);
114114
ArrayType *copy_intArrayType(ArrayType *a);
115115
ArrayType *resize_intArrayType(ArrayType *a, int num);
@@ -176,16 +176,12 @@ bool execconsistent(QUERYTYPE *query, ArrayType *array, bool calcnot);
176176
bool gin_bool_consistent(QUERYTYPE *query, bool *check);
177177
bool query_has_required_values(QUERYTYPE *query);
178178

179-
int compASC(const void *a, const void *b);
180-
int compDESC(const void *a, const void *b);
181-
182179
/* sort, either ascending or descending */
183180
#define QSORT(a, direction) \
184181
do { \
185182
int _nelems_ = ARRNELEMS(a); \
186-
if (_nelems_ > 1) \
187-
qsort((void*) ARRPTR(a), _nelems_, sizeof(int32), \
188-
(direction) ? compASC : compDESC ); \
183+
bool _asc = (direction) ? true : false; \
184+
isort(ARRPTR(a), _nelems_, &_asc); \
189185
} while(0)
190186

191187
#endif /* ___INT_H__ */

contrib/intarray/_int_tool.c

Lines changed: 26 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -186,36 +186,38 @@ rt__int_size(ArrayType *a, float *size)
186186
*size = (float) ARRNELEMS(a);
187187
}
188188

189-
/* qsort_arg comparison function for isort() */
190-
static int
189+
/* comparison function for isort() and _int_unique() */
190+
static inline int
191191
isort_cmp(const void *a, const void *b, void *arg)
192192
{
193193
int32 aval = *((const int32 *) a);
194194
int32 bval = *((const int32 *) b);
195195

196-
if (aval < bval)
197-
return -1;
198-
if (aval > bval)
199-
return 1;
200-
201-
/*
202-
* Report if we have any duplicates. If there are equal keys, qsort must
203-
* compare them at some point, else it wouldn't know whether one should go
204-
* before or after the other.
205-
*/
206-
*((bool *) arg) = true;
196+
if (*((bool *) arg))
197+
{
198+
/* compare for ascending order */
199+
if (aval < bval)
200+
return -1;
201+
if (aval > bval)
202+
return 1;
203+
}
204+
else
205+
{
206+
if (aval > bval)
207+
return -1;
208+
if (aval < bval)
209+
return 1;
210+
}
207211
return 0;
208212
}
209213

210-
/* Sort the given data (len >= 2). Return true if any duplicates found */
211-
bool
212-
isort(int32 *a, int len)
213-
{
214-
bool r = false;
215-
216-
qsort_arg(a, len, sizeof(int32), isort_cmp, &r);
217-
return r;
218-
}
214+
#define ST_SORT isort
215+
#define ST_ELEMENT_TYPE int32
216+
#define ST_COMPARE(a, b, ascending) isort_cmp(a, b, ascending)
217+
#define ST_COMPARE_ARG_TYPE void
218+
#define ST_SCOPE
219+
#define ST_DEFINE
220+
#include "lib/sort_template.h"
219221

220222
/* Create a new int array with room for "num" elements */
221223
ArrayType *
@@ -311,10 +313,10 @@ ArrayType *
311313
_int_unique(ArrayType *r)
312314
{
313315
int num = ARRNELEMS(r);
314-
bool duplicates_found; /* not used */
316+
bool ascending = true;
315317

316318
num = qunique_arg(ARRPTR(r), num, sizeof(int), isort_cmp,
317-
&duplicates_found);
319+
&ascending);
318320

319321
return resize_intArrayType(r, num);
320322
}
@@ -393,15 +395,3 @@ int_to_intset(int32 elem)
393395
aa[0] = elem;
394396
return result;
395397
}
396-
397-
int
398-
compASC(const void *a, const void *b)
399-
{
400-
return pg_cmp_s32(*(const int32 *) a, *(const int32 *) b);
401-
}
402-
403-
int
404-
compDESC(const void *a, const void *b)
405-
{
406-
return pg_cmp_s32(*(const int32 *) b, *(const int32 *) a);
407-
}

0 commit comments

Comments
 (0)