ip2net: some more optimize ipv6 sort

This commit is contained in:
bol-van 2022-06-17 10:35:20 +03:00
parent 732cb7f2d6
commit 76ae74eedd
9 changed files with 24 additions and 27 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -62,43 +62,39 @@ __attribute__((optimize ("no-strict-aliasing")))
#endif #endif
static int cmp6(const void * a, const void * b, void *arg) static int cmp6(const void * a, const void * b, void *arg)
{ {
// this function is critical to sort performance // this function is critical for sort performance
// on big endian systems cpu byte order is equal to network byte order // on big endian systems cpu byte order is equal to network byte order
// no conversion required. it's possible to improve speed by using big size compares // no conversion required. it's possible to improve speed by using big size compares
// on little endian systems byte conversion also gives better result than byte comparision // on little endian systems byte conversion also gives better result than byte comparision
// 64-bit archs often have cpu command to reverse byte order // 64-bit archs often have cpu command to reverse byte order
// assume that a and b are properly aligned // assume that a and b are properly aligned
#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__==__ORDER_BIG_ENDIAN__) && defined(__SIZEOF_INT128__)
// the fastest possible way (MIPS64/PPC64 only ?) #if defined(__BYTE_ORDER__) && ((__BYTE_ORDER__==__ORDER_BIG_ENDIAN__) || (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__))
const unsigned __int128 *pa = (unsigned __int128*)((struct in6_addr *)a)->s6_addr;
const unsigned __int128 *pb = (unsigned __int128*)((struct in6_addr *)b)->s6_addr; uint64_t aa,bb;
return *pa < *pb ? -1 : *pa == *pb ? 0 : 1;
#elif defined(__BYTE_ORDER__) && ((__BYTE_ORDER__==__ORDER_BIG_ENDIAN__) || (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__))
uint64_t am,al,bm,bl;
#if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
am = __builtin_bswap64(((uint64_t*)((struct in6_addr *)a)->s6_addr)[0]); aa = __builtin_bswap64(((uint64_t*)((struct in6_addr *)a)->s6_addr)[0]);
al = __builtin_bswap64(((uint64_t*)((struct in6_addr *)a)->s6_addr)[1]); bb = __builtin_bswap64(((uint64_t*)((struct in6_addr *)b)->s6_addr)[0]);
bm = __builtin_bswap64(((uint64_t*)((struct in6_addr *)b)->s6_addr)[0]);
bl = __builtin_bswap64(((uint64_t*)((struct in6_addr *)b)->s6_addr)[1]);
#else #else
am = ((uint64_t*)((struct in6_addr *)a)->s6_addr)[0]; aa = ((uint64_t*)((struct in6_addr *)a)->s6_addr)[0];
al = ((uint64_t*)((struct in6_addr *)a)->s6_addr)[1]; bb = ((uint64_t*)((struct in6_addr *)b)->s6_addr)[0];
bm = ((uint64_t*)((struct in6_addr *)b)->s6_addr)[0];
bl = ((uint64_t*)((struct in6_addr *)b)->s6_addr)[1];
#endif #endif
if (am < bm) if (aa < bb)
return -1; return -1;
else if (am == bm) else if (aa > bb)
return 1;
else
{ {
if (al < bl) #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
return -1; aa = __builtin_bswap64(((uint64_t*)((struct in6_addr *)a)->s6_addr)[1]);
else if (al > bl) bb = __builtin_bswap64(((uint64_t*)((struct in6_addr *)b)->s6_addr)[1]);
return 1; #else
else aa = ((uint64_t*)((struct in6_addr *)a)->s6_addr)[1];
return 0; bb = ((uint64_t*)((struct in6_addr *)b)->s6_addr)[1];
#endif
return aa < bb ? -1 : aa < bb ? 1 : 0;
} }
else
return 1;
#else #else
// fallback case // fallback case
for (uint8_t i = 0; i < sizeof(((struct in6_addr *)0)->s6_addr); i++) for (uint8_t i = 0; i < sizeof(((struct in6_addr *)0)->s6_addr); i++)
@ -111,6 +107,7 @@ static int cmp6(const void * a, const void * b, void *arg)
return 0; return 0;
#endif #endif
} }
// make presorted array unique. return number of unique items. // make presorted array unique. return number of unique items.
static uint32_t unique6(struct in6_addr *pu, uint32_t ct) static uint32_t unique6(struct in6_addr *pu, uint32_t ct)
{ {