ddt: compare keys 64-bits at a time, trying to match ZAP order
This yields substantial performance improvements when we only write out some small % of entries at a time, as it will cause entries that will go into "nearby" ZAP leaf nodes to be grouped closer together in the AVL, and so touch fewer blocks. Without this, the distribution is an even spread, so we touch a lot more ZAP leaf nodes for any given number of entries. Reviewed-by: Alexander Motin <mav@FreeBSD.org> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Co-authored-by: Allan Jude <allan@klarasystems.com> Signed-off-by: Rob Norris <rob.norris@klarasystems.com> Sponsored-by: Klara, Inc. Sponsored-by: iXsystems, Inc. Closes #15895
This commit is contained in:
parent
27e9cb5f80
commit
592f38900d
|
@ -1038,29 +1038,25 @@ ddt_prefetch(spa_t *spa, const blkptr_t *bp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Key comparison. Any struct wanting to make use of this function must have
|
* ddt_key_t comparison. Any struct wanting to make use of this function must
|
||||||
* the key as the first element.
|
* have the key as the first element. Casts it to N uint64_ts, and checks until
|
||||||
|
* we find there's a difference. This is intended to match how ddt_zap.c drives
|
||||||
|
* the ZAPs (first uint64_t as the key prehash), which will minimise the number
|
||||||
|
* of ZAP blocks touched when flushing logged entries from an AVL walk. This is
|
||||||
|
* not an invariant for this function though, should you wish to change it.
|
||||||
*/
|
*/
|
||||||
#define DDT_KEY_CMP_LEN (sizeof (ddt_key_t) / sizeof (uint16_t))
|
|
||||||
|
|
||||||
typedef struct ddt_key_cmp {
|
|
||||||
uint16_t u16[DDT_KEY_CMP_LEN];
|
|
||||||
} ddt_key_cmp_t;
|
|
||||||
|
|
||||||
int
|
int
|
||||||
ddt_key_compare(const void *x1, const void *x2)
|
ddt_key_compare(const void *x1, const void *x2)
|
||||||
{
|
{
|
||||||
const ddt_key_cmp_t *k1 = (const ddt_key_cmp_t *)x1;
|
const uint64_t *k1 = (const uint64_t *)x1;
|
||||||
const ddt_key_cmp_t *k2 = (const ddt_key_cmp_t *)x2;
|
const uint64_t *k2 = (const uint64_t *)x2;
|
||||||
int32_t cmp = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < DDT_KEY_CMP_LEN; i++) {
|
int cmp;
|
||||||
cmp = (int32_t)k1->u16[i] - (int32_t)k2->u16[i];
|
for (int i = 0; i < (sizeof (ddt_key_t) / sizeof (uint64_t)); i++)
|
||||||
if (likely(cmp))
|
if (likely((cmp = TREE_CMP(k1[i], k2[i])) != 0))
|
||||||
break;
|
return (cmp);
|
||||||
}
|
|
||||||
|
|
||||||
return (TREE_ISIGN(cmp));
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the containing dir for this DDT and bump the feature count */
|
/* Create the containing dir for this DDT and bump the feature count */
|
||||||
|
|
Loading…
Reference in New Issue