1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2026-05-22 10:15:16 +02:00

Improve sort comparators.

Improve sort comparators to use branchless comparisons when possible and avoid using subtraction. Only one comparator was using subtraction and it appears there was no overflow risk since the values were pretty small.

Inspired by https://www.postgresql.org/message-id/CA%2B14426g2Wa9QuUpmakwPxXFWG_1FaY0AsApkvcTBy-YfS6uaw%40mail.gmail.com.
This commit is contained in:
David Steele
2024-03-08 10:07:03 +13:00
committed by GitHub
parent e00bfe2d2c
commit 4387250f2e
7 changed files with 38 additions and 42 deletions
+13
View File
@@ -53,6 +53,19 @@
<p>Add detailed backtrace to <proper>autoconf</proper>/<proper>make</proper> build.</p>
</release-item>
</release-improvement-list>
<release-development-list>
<release-item>
<github-pull-request id="2280"/>
<release-item-contributor-list>
<release-item-contributor id="david.steele"/>
<release-item-reviewer id="stephen.frost"/>
</release-item-contributor-list>
<p>Improve sort comparators.</p>
</release-item>
</release-development-list>
</release-core-list>
<release-doc-list>
+8 -6
View File
@@ -15,6 +15,7 @@ Archive Common
#include "common/log.h"
#include "common/memContext.h"
#include "common/regExp.h"
#include "common/type/convert.h"
#include "common/wait.h"
#include "config/config.h"
#include "postgres/interface.h"
@@ -293,14 +294,15 @@ archiveAsyncExec(ArchiveMode archiveMode, const StringList *commandExec)
/**********************************************************************************************************************************/
FN_EXTERN int
archiveIdComparator(const void *item1, const void *item2)
archiveIdComparator(const void *const archiveId1, const void *const archiveId2)
{
StringList *archiveSort1 = strLstNewSplitZ(*(String **)item1, "-");
StringList *archiveSort2 = strLstNewSplitZ(*(String **)item2, "-");
int int1 = atoi(strZ(strLstGet(archiveSort1, 1)));
int int2 = atoi(strZ(strLstGet(archiveSort2, 1)));
ASSERT(strstr(strZ(*(String **)archiveId1), "-") != NULL);
ASSERT(strstr(strZ(*(String **)archiveId2), "-") != NULL);
return int1 - int2;
const int id1 = cvtZToInt(strstr(strZ(*(String **)archiveId1), "-") + 1);
const int id2 = cvtZToInt(strstr(strZ(*(String **)archiveId2), "-") + 1);
return LST_COMPARATOR_CMP(id1, id2);
}
/**********************************************************************************************************************************/
+3 -5
View File
@@ -76,12 +76,10 @@ lstComparatorBlockMapReference(const void *const blockMapRef1, const void *const
ASSERT(blockMapRef1 != NULL);
ASSERT(blockMapRef2 != NULL);
if (((BlockMapReference *)blockMapRef1)->reference < ((BlockMapReference *)blockMapRef2)->reference)
FUNCTION_TEST_RETURN(INT, -1);
else if (((BlockMapReference *)blockMapRef1)->reference > ((BlockMapReference *)blockMapRef2)->reference)
FUNCTION_TEST_RETURN(INT, 1);
const unsigned int reference1 = ((BlockMapReference *)blockMapRef1)->reference;
const unsigned int reference2 = ((BlockMapReference *)blockMapRef2)->reference;
FUNCTION_TEST_RETURN(INT, 0);
FUNCTION_TEST_RETURN(INT, LST_COMPARATOR_CMP(reference1, reference2));
}
FN_EXTERN BlockMap *
+8 -11
View File
@@ -89,23 +89,20 @@ lstComparatorStr(const void *item1, const void *item2)
/**********************************************************************************************************************************/
FN_EXTERN int
lstComparatorUInt(const void *const item1, const void *const item2)
lstComparatorUInt(const void *const uintPtr1, const void *const uintPtr2)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM_P(VOID, item1);
FUNCTION_TEST_PARAM_P(VOID, item2);
FUNCTION_TEST_PARAM_P(VOID, uintPtr1);
FUNCTION_TEST_PARAM_P(VOID, uintPtr2);
FUNCTION_TEST_END();
ASSERT(item1 != NULL);
ASSERT(item2 != NULL);
ASSERT(uintPtr1 != NULL);
ASSERT(uintPtr2 != NULL);
if (*(unsigned int *)item1 < *(unsigned int *)item2)
FUNCTION_TEST_RETURN(INT, -1);
const unsigned int uint1 = *(unsigned int *)uintPtr1;
const unsigned int uint2 = *(unsigned int *)uintPtr2;
if (*(unsigned int *)item1 > *(unsigned int *)item2)
FUNCTION_TEST_RETURN(INT, 1);
FUNCTION_TEST_RETURN(INT, 0);
FUNCTION_TEST_RETURN(INT, LST_COMPARATOR_CMP(uint1, uint2));
}
/**********************************************************************************************************************************/
+4
View File
@@ -52,6 +52,10 @@ FN_EXTERN int lstComparatorUInt(const void *item1, const void *item2);
// General purpose list comparator for zero-terminated strings or structs with a zero-terminated string as the first member
FN_EXTERN int lstComparatorZ(const void *item1, const void *item2);
// Macro to compare two values in a branchless and transitive fashion
#define LST_COMPARATOR_CMP(item1, item2) \
(((item1) > (item2)) - ((item1) < (item2)))
/***********************************************************************************************************************************
Constructors
***********************************************************************************************************************************/
+1 -10
View File
@@ -9,16 +9,7 @@ Test sort comparator
static int
testComparator(const void *item1, const void *item2)
{
int int1 = *(int *)item1;
int int2 = *(int *)item2;
if (int1 < int2)
return -1;
if (int1 > int2)
return 1;
return 0;
return LST_COMPARATOR_CMP(*(int *)item1, *(int *)item2);
}
/***********************************************************************************************************************************
+1 -10
View File
@@ -31,16 +31,7 @@ Test sort comparator
static int
testComparator(const void *item1, const void *item2)
{
int int1 = *(int *)item1;
int int2 = *(int *)item2;
if (int1 < int2)
return -1;
if (int1 > int2)
return 1;
return 0;
return LST_COMPARATOR_CMP(*(int *)item1, *(int *)item2);
}
/***********************************************************************************************************************************