Skip to content

Commit e246b3d

Browse files
committed
Add a fast pre-check for equality of equal-length strings.
Testing reveals that that doing a memcmp() before the strcoll() costs practically nothing, at least on the systems we tested, and it speeds up sorts containing many equal strings significatly. Peter Geoghegan. Review by myself and Heikki Linnakangas. Comments rewritten by me.
1 parent 491c029 commit e246b3d

File tree

1 file changed

+20
-0
lines changed

1 file changed

+20
-0
lines changed

src/backend/utils/adt/varlena.c

+20
Original file line numberDiff line numberDiff line change
@@ -1405,6 +1405,18 @@ varstr_cmp(char *arg1, int len1, char *arg2, int len2, Oid collid)
14051405
#endif
14061406
}
14071407

1408+
/*
1409+
* memcmp() can't tell us which of two unequal strings sorts first, but
1410+
* it's a cheap way to tell if they're equal. Testing shows that
1411+
* memcmp() followed by strcoll() is only trivially slower than
1412+
* strcoll() by itself, so we don't lose much if this doesn't work out
1413+
* very often, and if it does - for example, because there are many
1414+
* equal strings in the input - then we win big by avoiding expensive
1415+
* collation-aware comparisons.
1416+
*/
1417+
if (len1 == len2 && memcmp(arg1, arg2, len1) == 0)
1418+
return 0;
1419+
14081420
#ifdef WIN32
14091421
/* Win32 does not have UTF-8, so we need to map to UTF-16 */
14101422
if (GetDatabaseEncoding() == PG_UTF8)
@@ -1842,6 +1854,13 @@ bttextfastcmp_locale(Datum x, Datum y, SortSupport ssup)
18421854
len1 = VARSIZE_ANY_EXHDR(arg1);
18431855
len2 = VARSIZE_ANY_EXHDR(arg2);
18441856

1857+
/* Fast pre-check for equality, as discussed in varstr_cmp() */
1858+
if (len1 == len2 && memcmp(a1p, a2p, len1) == 0)
1859+
{
1860+
result = 0;
1861+
goto done;
1862+
}
1863+
18451864
if (len1 >= tss->buflen1)
18461865
{
18471866
pfree(tss->buf1);
@@ -1875,6 +1894,7 @@ bttextfastcmp_locale(Datum x, Datum y, SortSupport ssup)
18751894
if (result == 0)
18761895
result = strcmp(tss->buf1, tss->buf2);
18771896

1897+
done:
18781898
/* We can't afford to leak memory here. */
18791899
if (PointerGetDatum(arg1) != x)
18801900
pfree(arg1);

0 commit comments

Comments
 (0)