aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndriy Gapon <avg@FreeBSD.org>2019-10-16 08:01:36 +0000
committerAndriy Gapon <avg@FreeBSD.org>2019-10-16 08:01:36 +0000
commit37075672d24ed267c3389dd2b7179efa83516fcc (patch)
tree114455bc8cf877c9a26403de2328bba68c64847e
parent74032c5f3b4b5ae87cbc8254a095b485391c3b79 (diff)
downloadsrc-37075672d24ed267c3389dd2b7179efa83516fcc.tar.gz
src-37075672d24ed267c3389dd2b7179efa83516fcc.zip
10809 Performance optimization of AVL tree comparator functions
illumos/illumos-gate@c4ab0d3f46036e85ad0700125c5a83cc139f55a3 https://github.com/illumos/illumos-gate/commit/c4ab0d3f46036e85ad0700125c5a83cc139f55a3 https://www.illumos.org/issues/10809 Port ZoL ee36c709c3d Performance optimization of AVL tree comparator functions From the ZoL commit msg: perf: 2.75x faster ddt_entry_compare() First 256bits of ddt_key_t is a block checksum, which are expected to be close to random data. Hence, on average, comparison only needs to look at first few bytes of the keys. To reduce number of conditional jump instructions, the result is computed as: sign(memcmp(k1, k2)). Sign of an integer 'a' can be obtained as: `(0 < a) - (a < 0)` := {-1, 0, 1}, which is computed efficiently. Synthetic performance evaluation of original and new algorithm over 1G random keys on 2.6GHz Intel(R) Xeon(R) CPU E5-2660 v3: old 6.85789 s new 2.49089 s perf: 2.8x faster vdev_queue_offset_compare() and vdev_queue_timestamp_compare() Compute the result directly instead of using conditionals perf: zfs_range_compare() Speedup between 1.1x - 2.5x, depending on compiler version and optimization level. perf: spa_error_entry_compare() `bcmp()` is not suitable for comparator use. Use `memcmp()` instead. perf: 2.8x faster metaslab_compare() and metaslab_rangesize_compare() perf: 2.8x faster zil_bp_compare() Portions contributed by: Jerry Jelinek <jerry.jelinek@joyent.com> Author: Gvozden Neskovic <neskovic@gmail.com>
Notes
Notes: svn path=/vendor-sys/illumos/dist/; revision=353630
-rw-r--r--lib/libzfs/common/libzfs_dataset.c8
-rw-r--r--lib/libzfs/common/libzfs_iter.c7
-rw-r--r--lib/libzfs/common/libzfs_sendrecv.c11
-rw-r--r--lib/libzpool/common/sys/zfs_context.h8
-rw-r--r--uts/common/fs/zfs/ddt.c27
-rw-r--r--uts/common/fs/zfs/dnode.c26
-rw-r--r--uts/common/fs/zfs/dsl_deadlist.c11
-rw-r--r--uts/common/fs/zfs/dsl_deleg.c9
-rw-r--r--uts/common/fs/zfs/lz4.c5
-rw-r--r--uts/common/fs/zfs/metaslab.c38
-rw-r--r--uts/common/fs/zfs/range_tree.c19
-rw-r--r--uts/common/fs/zfs/sa.c28
-rw-r--r--uts/common/fs/zfs/spa.c13
-rw-r--r--uts/common/fs/zfs/spa_misc.c20
-rw-r--r--uts/common/fs/zfs/space_reftree.c18
-rw-r--r--uts/common/fs/zfs/sys/zfs_context.h8
-rw-r--r--uts/common/fs/zfs/unique.c12
-rw-r--r--uts/common/fs/zfs/vdev_cache.c25
-rw-r--r--uts/common/fs/zfs/vdev_label.c16
-rw-r--r--uts/common/fs/zfs/vdev_queue.c34
-rw-r--r--uts/common/fs/zfs/zap_micro.c14
-rw-r--r--uts/common/fs/zfs/zfs_fuid.c19
-rw-r--r--uts/common/fs/zfs/zfs_rlock.c12
-rw-r--r--uts/common/fs/zfs/zil.c28
-rw-r--r--uts/common/sys/avl.h7
25 files changed, 163 insertions, 260 deletions
diff --git a/lib/libzfs/common/libzfs_dataset.c b/lib/libzfs/common/libzfs_dataset.c
index 980a1b736643..a141c6a73725 100644
--- a/lib/libzfs/common/libzfs_dataset.c
+++ b/lib/libzfs/common/libzfs_dataset.c
@@ -772,15 +772,13 @@ typedef struct mnttab_node {
static int
libzfs_mnttab_cache_compare(const void *arg1, const void *arg2)
{
- const mnttab_node_t *mtn1 = arg1;
- const mnttab_node_t *mtn2 = arg2;
+ const mnttab_node_t *mtn1 = (const mnttab_node_t *)arg1;
+ const mnttab_node_t *mtn2 = (const mnttab_node_t *)arg2;
int rv;
rv = strcmp(mtn1->mtn_mt.mnt_special, mtn2->mtn_mt.mnt_special);
- if (rv == 0)
- return (0);
- return (rv > 0 ? 1 : -1);
+ return (AVL_ISIGN(rv));
}
void
diff --git a/lib/libzfs/common/libzfs_iter.c b/lib/libzfs/common/libzfs_iter.c
index b0cb1ff18641..bdef9757efb2 100644
--- a/lib/libzfs/common/libzfs_iter.c
+++ b/lib/libzfs/common/libzfs_iter.c
@@ -272,12 +272,7 @@ zfs_snapshot_compare(const void *larg, const void *rarg)
lcreate = zfs_prop_get_int(l, ZFS_PROP_CREATETXG);
rcreate = zfs_prop_get_int(r, ZFS_PROP_CREATETXG);
- if (lcreate < rcreate)
- return (-1);
- else if (lcreate > rcreate)
- return (+1);
- else
- return (0);
+ return (AVL_CMP(lcreate, rcreate));
}
int
diff --git a/lib/libzfs/common/libzfs_sendrecv.c b/lib/libzfs/common/libzfs_sendrecv.c
index e56aa7f7c167..7ed81fd0d16a 100644
--- a/lib/libzfs/common/libzfs_sendrecv.c
+++ b/lib/libzfs/common/libzfs_sendrecv.c
@@ -482,15 +482,10 @@ typedef struct fsavl_node {
static int
fsavl_compare(const void *arg1, const void *arg2)
{
- const fsavl_node_t *fn1 = arg1;
- const fsavl_node_t *fn2 = arg2;
+ const fsavl_node_t *fn1 = (const fsavl_node_t *)arg1;
+ const fsavl_node_t *fn2 = (const fsavl_node_t *)arg2;
- if (fn1->fn_guid > fn2->fn_guid)
- return (+1);
- else if (fn1->fn_guid < fn2->fn_guid)
- return (-1);
- else
- return (0);
+ return (AVL_CMP(fn1->fn_guid, fn2->fn_guid));
}
/*
diff --git a/lib/libzpool/common/sys/zfs_context.h b/lib/libzpool/common/sys/zfs_context.h
index d1dce8019607..8612aefb0fa7 100644
--- a/lib/libzpool/common/sys/zfs_context.h
+++ b/lib/libzpool/common/sys/zfs_context.h
@@ -285,6 +285,14 @@ extern vnode_t *rootdir;
#define minclsyspri 60
#define maxclsyspri 99
+#if (GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__)
+#define _zfs_expect(expr, value) (__builtin_expect((expr), (value)))
+#else
+#define _zfs_expect(expr, value) (expr)
+#endif
+
+#define likely(x) _zfs_expect((x) != 0, 1)
+
#define CPU_SEQID (thr_self() & (max_ncpus - 1))
extern void kernel_init(int);
diff --git a/uts/common/fs/zfs/ddt.c b/uts/common/fs/zfs/ddt.c
index 06c51fe05bb6..963ecbd58fa7 100644
--- a/uts/common/fs/zfs/ddt.c
+++ b/uts/common/fs/zfs/ddt.c
@@ -755,22 +755,31 @@ ddt_prefetch(spa_t *spa, const blkptr_t *bp)
}
}
+/*
+ * Opaque struct used for ddt_key comparison
+ */
+#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
ddt_entry_compare(const void *x1, const void *x2)
{
const ddt_entry_t *dde1 = x1;
const ddt_entry_t *dde2 = x2;
- const uint64_t *u1 = (const uint64_t *)&dde1->dde_key;
- const uint64_t *u2 = (const uint64_t *)&dde2->dde_key;
-
- for (int i = 0; i < DDT_KEY_WORDS; i++) {
- if (u1[i] < u2[i])
- return (-1);
- if (u1[i] > u2[i])
- return (1);
+ const ddt_key_cmp_t *k1 = (const ddt_key_cmp_t *)&dde1->dde_key;
+ const ddt_key_cmp_t *k2 = (const ddt_key_cmp_t *)&dde2->dde_key;
+ int32_t cmp = 0;
+
+ for (int i = 0; i < DDT_KEY_CMP_LEN; i++) {
+ cmp = (int32_t)k1->u16[i] - (int32_t)k2->u16[i];
+ if (likely(cmp))
+ break;
}
- return (0);
+ return (AVL_ISIGN(cmp));
}
static ddt_t *
diff --git a/uts/common/fs/zfs/dnode.c b/uts/common/fs/zfs/dnode.c
index 2f9e1884544a..f360eb997e18 100644
--- a/uts/common/fs/zfs/dnode.c
+++ b/uts/common/fs/zfs/dnode.c
@@ -90,19 +90,13 @@ dbuf_compare(const void *x1, const void *x2)
const dmu_buf_impl_t *d1 = x1;
const dmu_buf_impl_t *d2 = x2;
- if (d1->db_level < d2->db_level) {
- return (-1);
- }
- if (d1->db_level > d2->db_level) {
- return (1);
- }
+ int cmp = AVL_CMP(d1->db_level, d2->db_level);
+ if (likely(cmp))
+ return (cmp);
- if (d1->db_blkid < d2->db_blkid) {
- return (-1);
- }
- if (d1->db_blkid > d2->db_blkid) {
- return (1);
- }
+ cmp = AVL_CMP(d1->db_blkid, d2->db_blkid);
+ if (likely(cmp))
+ return (cmp);
if (d1->db_state == DB_SEARCH) {
ASSERT3S(d2->db_state, !=, DB_SEARCH);
@@ -112,13 +106,7 @@ dbuf_compare(const void *x1, const void *x2)
return (1);
}
- if ((uintptr_t)d1 < (uintptr_t)d2) {
- return (-1);
- }
- if ((uintptr_t)d1 > (uintptr_t)d2) {
- return (1);
- }
- return (0);
+ return (AVL_PCMP(d1, d2));
}
/* ARGSUSED */
diff --git a/uts/common/fs/zfs/dsl_deadlist.c b/uts/common/fs/zfs/dsl_deadlist.c
index 356e5b51c3f4..2f3647bc8e86 100644
--- a/uts/common/fs/zfs/dsl_deadlist.c
+++ b/uts/common/fs/zfs/dsl_deadlist.c
@@ -55,15 +55,10 @@
static int
dsl_deadlist_compare(const void *arg1, const void *arg2)
{
- const dsl_deadlist_entry_t *dle1 = arg1;
- const dsl_deadlist_entry_t *dle2 = arg2;
+ const dsl_deadlist_entry_t *dle1 = (const dsl_deadlist_entry_t *)arg1;
+ const dsl_deadlist_entry_t *dle2 = (const dsl_deadlist_entry_t *)arg2;
- if (dle1->dle_mintxg < dle2->dle_mintxg)
- return (-1);
- else if (dle1->dle_mintxg > dle2->dle_mintxg)
- return (+1);
- else
- return (0);
+ return (AVL_CMP(dle1->dle_mintxg, dle2->dle_mintxg));
}
static void
diff --git a/uts/common/fs/zfs/dsl_deleg.c b/uts/common/fs/zfs/dsl_deleg.c
index b2f69045a64b..e72c66ade6fd 100644
--- a/uts/common/fs/zfs/dsl_deleg.c
+++ b/uts/common/fs/zfs/dsl_deleg.c
@@ -384,14 +384,13 @@ typedef struct perm_set {
static int
perm_set_compare(const void *arg1, const void *arg2)
{
- const perm_set_t *node1 = arg1;
- const perm_set_t *node2 = arg2;
+ const perm_set_t *node1 = (const perm_set_t *)arg1;
+ const perm_set_t *node2 = (const perm_set_t *)arg2;
int val;
val = strcmp(node1->p_setname, node2->p_setname);
- if (val == 0)
- return (0);
- return (val > 0 ? 1 : -1);
+
+ return (AVL_ISIGN(val));
}
/*
diff --git a/uts/common/fs/zfs/lz4.c b/uts/common/fs/zfs/lz4.c
index 82a08939dca3..6426ba67b231 100644
--- a/uts/common/fs/zfs/lz4.c
+++ b/uts/common/fs/zfs/lz4.c
@@ -284,8 +284,13 @@ lz4_decompress(void *s_start, void *d_start, size_t s_len, size_t d_len, int n)
#define expect(expr, value) (expr)
#endif
+#ifndef likely
#define likely(expr) expect((expr) != 0, 1)
+#endif
+
+#ifndef unlikely
#define unlikely(expr) expect((expr) != 0, 0)
+#endif
/* Basic types */
#if defined(_MSC_VER)
diff --git a/uts/common/fs/zfs/metaslab.c b/uts/common/fs/zfs/metaslab.c
index 44fc2b0e8604..d5a3e7232ac2 100644
--- a/uts/common/fs/zfs/metaslab.c
+++ b/uts/common/fs/zfs/metaslab.c
@@ -451,8 +451,8 @@ metaslab_class_expandable_space(metaslab_class_t *mc)
static int
metaslab_compare(const void *x1, const void *x2)
{
- const metaslab_t *m1 = x1;
- const metaslab_t *m2 = x2;
+ const metaslab_t *m1 = (const metaslab_t *)x1;
+ const metaslab_t *m2 = (const metaslab_t *)x2;
int sort1 = 0;
int sort2 = 0;
@@ -478,22 +478,13 @@ metaslab_compare(const void *x1, const void *x2)
if (sort1 > sort2)
return (1);
- if (m1->ms_weight < m2->ms_weight)
- return (1);
- if (m1->ms_weight > m2->ms_weight)
- return (-1);
-
- /*
- * If the weights are identical, use the offset to force uniqueness.
- */
- if (m1->ms_start < m2->ms_start)
- return (-1);
- if (m1->ms_start > m2->ms_start)
- return (1);
+ int cmp = AVL_CMP(m2->ms_weight, m1->ms_weight);
+ if (likely(cmp))
+ return (cmp);
- ASSERT3P(m1, ==, m2);
+ IMPLY(AVL_CMP(m1->ms_start, m2->ms_start) == 0, m1 == m2);
- return (0);
+ return (AVL_CMP(m1->ms_start, m2->ms_start));
}
/*
@@ -1104,18 +1095,11 @@ metaslab_rangesize_compare(const void *x1, const void *x2)
uint64_t rs_size1 = r1->rs_end - r1->rs_start;
uint64_t rs_size2 = r2->rs_end - r2->rs_start;
- if (rs_size1 < rs_size2)
- return (-1);
- if (rs_size1 > rs_size2)
- return (1);
-
- if (r1->rs_start < r2->rs_start)
- return (-1);
+ int cmp = AVL_CMP(rs_size1, rs_size2);
+ if (likely(cmp))
+ return (cmp);
- if (r1->rs_start > r2->rs_start)
- return (1);
-
- return (0);
+ return (AVL_CMP(r1->rs_start, r2->rs_start));
}
/*
diff --git a/uts/common/fs/zfs/range_tree.c b/uts/common/fs/zfs/range_tree.c
index a0b9e5f9a1fe..99bdacb87deb 100644
--- a/uts/common/fs/zfs/range_tree.c
+++ b/uts/common/fs/zfs/range_tree.c
@@ -109,20 +109,13 @@ range_tree_stat_decr(range_tree_t *rt, range_seg_t *rs)
static int
range_tree_seg_compare(const void *x1, const void *x2)
{
- const range_seg_t *r1 = x1;
- const range_seg_t *r2 = x2;
+ const range_seg_t *r1 = (const range_seg_t *)x1;
+ const range_seg_t *r2 = (const range_seg_t *)x2;
- if (r1->rs_start < r2->rs_start) {
- if (r1->rs_end > r2->rs_start)
- return (0);
- return (-1);
- }
- if (r1->rs_start > r2->rs_start) {
- if (r1->rs_start < r2->rs_end)
- return (0);
- return (1);
- }
- return (0);
+ ASSERT3U(r1->rs_start, <=, r1->rs_end);
+ ASSERT3U(r2->rs_start, <=, r2->rs_end);
+
+ return ((r1->rs_start >= r2->rs_end) - (r1->rs_end <= r2->rs_start));
}
range_tree_t *
diff --git a/uts/common/fs/zfs/sa.c b/uts/common/fs/zfs/sa.c
index d8cf42db5fa8..d3c0a3e8ef50 100644
--- a/uts/common/fs/zfs/sa.c
+++ b/uts/common/fs/zfs/sa.c
@@ -243,31 +243,23 @@ sa_cache_fini(void)
static int
layout_num_compare(const void *arg1, const void *arg2)
{
- const sa_lot_t *node1 = arg1;
- const sa_lot_t *node2 = arg2;
+ const sa_lot_t *node1 = (const sa_lot_t *)arg1;
+ const sa_lot_t *node2 = (const sa_lot_t *)arg2;
- if (node1->lot_num > node2->lot_num)
- return (1);
- else if (node1->lot_num < node2->lot_num)
- return (-1);
- return (0);
+ return (AVL_CMP(node1->lot_num, node2->lot_num));
}
static int
layout_hash_compare(const void *arg1, const void *arg2)
{
- const sa_lot_t *node1 = arg1;
- const sa_lot_t *node2 = arg2;
+ const sa_lot_t *node1 = (const sa_lot_t *)arg1;
+ const sa_lot_t *node2 = (const sa_lot_t *)arg2;
- if (node1->lot_hash > node2->lot_hash)
- return (1);
- if (node1->lot_hash < node2->lot_hash)
- return (-1);
- if (node1->lot_instance > node2->lot_instance)
- return (1);
- if (node1->lot_instance < node2->lot_instance)
- return (-1);
- return (0);
+ int cmp = AVL_CMP(node1->lot_hash, node2->lot_hash);
+ if (likely(cmp))
+ return (cmp);
+
+ return (AVL_CMP(node1->lot_instance, node2->lot_instance));
}
boolean_t
diff --git a/uts/common/fs/zfs/spa.c b/uts/common/fs/zfs/spa.c
index d833e2a06a3f..341fbcd6e9fc 100644
--- a/uts/common/fs/zfs/spa.c
+++ b/uts/common/fs/zfs/spa.c
@@ -882,19 +882,14 @@ spa_change_guid(spa_t *spa)
static int
spa_error_entry_compare(const void *a, const void *b)
{
- spa_error_entry_t *sa = (spa_error_entry_t *)a;
- spa_error_entry_t *sb = (spa_error_entry_t *)b;
+ const spa_error_entry_t *sa = (const spa_error_entry_t *)a;
+ const spa_error_entry_t *sb = (const spa_error_entry_t *)b;
int ret;
- ret = bcmp(&sa->se_bookmark, &sb->se_bookmark,
+ ret = memcmp(&sa->se_bookmark, &sb->se_bookmark,
sizeof (zbookmark_phys_t));
- if (ret < 0)
- return (-1);
- else if (ret > 0)
- return (1);
- else
- return (0);
+ return (AVL_ISIGN(ret));
}
/*
diff --git a/uts/common/fs/zfs/spa_misc.c b/uts/common/fs/zfs/spa_misc.c
index 944e684d9706..7a3998a0a8d9 100644
--- a/uts/common/fs/zfs/spa_misc.c
+++ b/uts/common/fs/zfs/spa_misc.c
@@ -897,18 +897,13 @@ typedef struct spa_aux {
int aux_count;
} spa_aux_t;
-static int
+static inline int
spa_aux_compare(const void *a, const void *b)
{
- const spa_aux_t *sa = a;
- const spa_aux_t *sb = b;
+ const spa_aux_t *sa = (const spa_aux_t *)a;
+ const spa_aux_t *sb = (const spa_aux_t *)b;
- if (sa->aux_guid < sb->aux_guid)
- return (-1);
- else if (sa->aux_guid > sb->aux_guid)
- return (1);
- else
- return (0);
+ return (AVL_CMP(sa->aux_guid, sb->aux_guid));
}
void
@@ -1878,11 +1873,8 @@ spa_name_compare(const void *a1, const void *a2)
int s;
s = strcmp(s1->spa_name, s2->spa_name);
- if (s > 0)
- return (1);
- if (s < 0)
- return (-1);
- return (0);
+
+ return (AVL_ISIGN(s));
}
int
diff --git a/uts/common/fs/zfs/space_reftree.c b/uts/common/fs/zfs/space_reftree.c
index a866e65d54f7..aa289ba1061d 100644
--- a/uts/common/fs/zfs/space_reftree.c
+++ b/uts/common/fs/zfs/space_reftree.c
@@ -54,20 +54,14 @@
static int
space_reftree_compare(const void *x1, const void *x2)
{
- const space_ref_t *sr1 = x1;
- const space_ref_t *sr2 = x2;
+ const space_ref_t *sr1 = (const space_ref_t *)x1;
+ const space_ref_t *sr2 = (const space_ref_t *)x2;
- if (sr1->sr_offset < sr2->sr_offset)
- return (-1);
- if (sr1->sr_offset > sr2->sr_offset)
- return (1);
+ int cmp = AVL_CMP(sr1->sr_offset, sr2->sr_offset);
+ if (likely(cmp))
+ return (cmp);
- if (sr1 < sr2)
- return (-1);
- if (sr1 > sr2)
- return (1);
-
- return (0);
+ return (AVL_PCMP(sr1, sr2));
}
void
diff --git a/uts/common/fs/zfs/sys/zfs_context.h b/uts/common/fs/zfs/sys/zfs_context.h
index 37de17b4a412..ebcdc7f111b5 100644
--- a/uts/common/fs/zfs/sys/zfs_context.h
+++ b/uts/common/fs/zfs/sys/zfs_context.h
@@ -73,6 +73,14 @@ extern "C" {
#include <sys/disp.h>
#include <sys/callo.h>
+#if (GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__)
+#define _zfs_expect(expr, value) (__builtin_expect((expr), (value)))
+#else
+#define _zfs_expect(expr, value) (expr)
+#endif
+
+#define likely(x) _zfs_expect((x) != 0, 1)
+
#define CPU_SEQID (CPU->cpu_seqid)
#ifdef __cplusplus
diff --git a/uts/common/fs/zfs/unique.c b/uts/common/fs/zfs/unique.c
index fbe7b619a29a..d33f451938b8 100644
--- a/uts/common/fs/zfs/unique.c
+++ b/uts/common/fs/zfs/unique.c
@@ -42,14 +42,10 @@ typedef struct unique {
static int
unique_compare(const void *a, const void *b)
{
- const unique_t *una = a;
- const unique_t *unb = b;
-
- if (una->un_value < unb->un_value)
- return (-1);
- if (una->un_value > unb->un_value)
- return (+1);
- return (0);
+ const unique_t *una = (const unique_t *)a;
+ const unique_t *unb = (const unique_t *)b;
+
+ return (AVL_CMP(una->un_value, unb->un_value));
}
void
diff --git a/uts/common/fs/zfs/vdev_cache.c b/uts/common/fs/zfs/vdev_cache.c
index 9b4755321d0d..34ae6d5270da 100644
--- a/uts/common/fs/zfs/vdev_cache.c
+++ b/uts/common/fs/zfs/vdev_cache.c
@@ -105,29 +105,24 @@ static vdc_stats_t vdc_stats = {
#define VDCSTAT_BUMP(stat) atomic_inc_64(&vdc_stats.stat.value.ui64);
-static int
+static inline int
vdev_cache_offset_compare(const void *a1, const void *a2)
{
- const vdev_cache_entry_t *ve1 = a1;
- const vdev_cache_entry_t *ve2 = a2;
-
- if (ve1->ve_offset < ve2->ve_offset)
- return (-1);
- if (ve1->ve_offset > ve2->ve_offset)
- return (1);
- return (0);
+ const vdev_cache_entry_t *ve1 = (const vdev_cache_entry_t *)a1;
+ const vdev_cache_entry_t *ve2 = (const vdev_cache_entry_t *)a2;
+
+ return (AVL_CMP(ve1->ve_offset, ve2->ve_offset));
}
static int
vdev_cache_lastused_compare(const void *a1, const void *a2)
{
- const vdev_cache_entry_t *ve1 = a1;
- const vdev_cache_entry_t *ve2 = a2;
+ const vdev_cache_entry_t *ve1 = (const vdev_cache_entry_t *)a1;
+ const vdev_cache_entry_t *ve2 = (const vdev_cache_entry_t *)a2;
- if (ve1->ve_lastused < ve2->ve_lastused)
- return (-1);
- if (ve1->ve_lastused > ve2->ve_lastused)
- return (1);
+ int cmp = AVL_CMP(ve1->ve_lastused, ve2->ve_lastused);
+ if (likely(cmp))
+ return (cmp);
/*
* Among equally old entries, sort by offset to ensure uniqueness.
diff --git a/uts/common/fs/zfs/vdev_label.c b/uts/common/fs/zfs/vdev_label.c
index 8d5f17c15f76..352bbe849283 100644
--- a/uts/common/fs/zfs/vdev_label.c
+++ b/uts/common/fs/zfs/vdev_label.c
@@ -989,19 +989,13 @@ retry:
* among uberblocks with equal txg, choose the one with the latest timestamp.
*/
static int
-vdev_uberblock_compare(uberblock_t *ub1, uberblock_t *ub2)
+vdev_uberblock_compare(const uberblock_t *ub1, const uberblock_t *ub2)
{
- if (ub1->ub_txg < ub2->ub_txg)
- return (-1);
- if (ub1->ub_txg > ub2->ub_txg)
- return (1);
+ int cmp = AVL_CMP(ub1->ub_txg, ub2->ub_txg);
+ if (likely(cmp))
+ return (cmp);
- if (ub1->ub_timestamp < ub2->ub_timestamp)
- return (-1);
- if (ub1->ub_timestamp > ub2->ub_timestamp)
- return (1);
-
- return (0);
+ return (AVL_CMP(ub1->ub_timestamp, ub2->ub_timestamp));
}
struct ubl_cbdata {
diff --git a/uts/common/fs/zfs/vdev_queue.c b/uts/common/fs/zfs/vdev_queue.c
index f29f4eeb9db5..dff83e3108f5 100644
--- a/uts/common/fs/zfs/vdev_queue.c
+++ b/uts/common/fs/zfs/vdev_queue.c
@@ -202,20 +202,15 @@ int zfs_vdev_def_queue_depth = 32;
int
vdev_queue_offset_compare(const void *x1, const void *x2)
{
- const zio_t *z1 = x1;
- const zio_t *z2 = x2;
+ const zio_t *z1 = (const zio_t *)x1;
+ const zio_t *z2 = (const zio_t *)x2;
- if (z1->io_offset < z2->io_offset)
- return (-1);
- if (z1->io_offset > z2->io_offset)
- return (1);
+ int cmp = AVL_CMP(z1->io_offset, z2->io_offset);
- if (z1 < z2)
- return (-1);
- if (z1 > z2)
- return (1);
+ if (likely(cmp))
+ return (cmp);
- return (0);
+ return (AVL_PCMP(z1, z2));
}
static inline avl_tree_t *
@@ -237,20 +232,15 @@ vdev_queue_type_tree(vdev_queue_t *vq, zio_type_t t)
int
vdev_queue_timestamp_compare(const void *x1, const void *x2)
{
- const zio_t *z1 = x1;
- const zio_t *z2 = x2;
+ const zio_t *z1 = (const zio_t *)x1;
+ const zio_t *z2 = (const zio_t *)x2;
- if (z1->io_timestamp < z2->io_timestamp)
- return (-1);
- if (z1->io_timestamp > z2->io_timestamp)
- return (1);
+ int cmp = AVL_CMP(z1->io_timestamp, z2->io_timestamp);
- if (z1 < z2)
- return (-1);
- if (z1 > z2)
- return (1);
+ if (likely(cmp))
+ return (cmp);
- return (0);
+ return (AVL_PCMP(z1, z2));
}
void
diff --git a/uts/common/fs/zfs/zap_micro.c b/uts/common/fs/zfs/zap_micro.c
index bb5da13ba152..48b0be666564 100644
--- a/uts/common/fs/zfs/zap_micro.c
+++ b/uts/common/fs/zfs/zap_micro.c
@@ -281,15 +281,11 @@ mze_compare(const void *arg1, const void *arg2)
const mzap_ent_t *mze1 = arg1;
const mzap_ent_t *mze2 = arg2;
- if (mze1->mze_hash > mze2->mze_hash)
- return (+1);
- if (mze1->mze_hash < mze2->mze_hash)
- return (-1);
- if (mze1->mze_cd > mze2->mze_cd)
- return (+1);
- if (mze1->mze_cd < mze2->mze_cd)
- return (-1);
- return (0);
+ int cmp = AVL_CMP(mze1->mze_hash, mze2->mze_hash);
+ if (likely(cmp))
+ return (cmp);
+
+ return (AVL_CMP(mze1->mze_cd, mze2->mze_cd));
}
static void
diff --git a/uts/common/fs/zfs/zfs_fuid.c b/uts/common/fs/zfs/zfs_fuid.c
index 6eb03c2c1840..7877a97b49e3 100644
--- a/uts/common/fs/zfs/zfs_fuid.c
+++ b/uts/common/fs/zfs/zfs_fuid.c
@@ -71,14 +71,10 @@ static char *nulldomain = "";
static int
idx_compare(const void *arg1, const void *arg2)
{
- const fuid_domain_t *node1 = arg1;
- const fuid_domain_t *node2 = arg2;
+ const fuid_domain_t *node1 = (const fuid_domain_t *)arg1;
+ const fuid_domain_t *node2 = (const fuid_domain_t *)arg2;
- if (node1->f_idx < node2->f_idx)
- return (-1);
- else if (node1->f_idx > node2->f_idx)
- return (1);
- return (0);
+ return (AVL_CMP(node1->f_idx, node2->f_idx));
}
/*
@@ -87,14 +83,13 @@ idx_compare(const void *arg1, const void *arg2)
static int
domain_compare(const void *arg1, const void *arg2)
{
- const fuid_domain_t *node1 = arg1;
- const fuid_domain_t *node2 = arg2;
+ const fuid_domain_t *node1 = (const fuid_domain_t *)arg1;
+ const fuid_domain_t *node2 = (const fuid_domain_t *)arg2;
int val;
val = strcmp(node1->f_ksid->kd_name, node2->f_ksid->kd_name);
- if (val == 0)
- return (0);
- return (val > 0 ? 1 : -1);
+
+ return (AVL_ISIGN(val));
}
void
diff --git a/uts/common/fs/zfs/zfs_rlock.c b/uts/common/fs/zfs/zfs_rlock.c
index 4e80ab27cce9..6c2f39bca383 100644
--- a/uts/common/fs/zfs/zfs_rlock.c
+++ b/uts/common/fs/zfs/zfs_rlock.c
@@ -106,14 +106,10 @@
static int
rangelock_compare(const void *arg1, const void *arg2)
{
- const locked_range_t *rl1 = arg1;
- const locked_range_t *rl2 = arg2;
-
- if (rl1->lr_offset > rl2->lr_offset)
- return (1);
- if (rl1->lr_offset < rl2->lr_offset)
- return (-1);
- return (0);
+ const locked_range_t *rl1 = (const locked_range_t *)arg1;
+ const locked_range_t *rl2 = (const locked_range_t *)arg2;
+
+ return (AVL_CMP(rl1->lr_offset, rl2->lr_offset));
}
/*
diff --git a/uts/common/fs/zfs/zil.c b/uts/common/fs/zfs/zil.c
index 44df4c96f3ce..44cd5bfb6e47 100644
--- a/uts/common/fs/zfs/zil.c
+++ b/uts/common/fs/zfs/zil.c
@@ -123,17 +123,11 @@ zil_bp_compare(const void *x1, const void *x2)
const dva_t *dva1 = &((zil_bp_node_t *)x1)->zn_dva;
const dva_t *dva2 = &((zil_bp_node_t *)x2)->zn_dva;
- if (DVA_GET_VDEV(dva1) < DVA_GET_VDEV(dva2))
- return (-1);
- if (DVA_GET_VDEV(dva1) > DVA_GET_VDEV(dva2))
- return (1);
-
- if (DVA_GET_OFFSET(dva1) < DVA_GET_OFFSET(dva2))
- return (-1);
- if (DVA_GET_OFFSET(dva1) > DVA_GET_OFFSET(dva2))
- return (1);
+ int cmp = AVL_CMP(DVA_GET_VDEV(dva1), DVA_GET_VDEV(dva2));
+ if (likely(cmp))
+ return (cmp);
- return (0);
+ return (AVL_CMP(DVA_GET_OFFSET(dva1), DVA_GET_OFFSET(dva2)));
}
static void
@@ -495,12 +489,7 @@ zil_lwb_vdev_compare(const void *x1, const void *x2)
const uint64_t v1 = ((zil_vdev_node_t *)x1)->zv_vdev;
const uint64_t v2 = ((zil_vdev_node_t *)x2)->zv_vdev;
- if (v1 < v2)
- return (-1);
- if (v1 > v2)
- return (1);
-
- return (0);
+ return (AVL_CMP(v1, v2));
}
static lwb_t *
@@ -1729,12 +1718,7 @@ zil_aitx_compare(const void *x1, const void *x2)
const uint64_t o1 = ((itx_async_node_t *)x1)->ia_foid;
const uint64_t o2 = ((itx_async_node_t *)x2)->ia_foid;
- if (o1 < o2)
- return (-1);
- if (o1 > o2)
- return (1);
-
- return (0);
+ return (AVL_CMP(o1, o2));
}
/*
diff --git a/uts/common/sys/avl.h b/uts/common/sys/avl.h
index 10e0ddaeef88..ba51e2a790f4 100644
--- a/uts/common/sys/avl.h
+++ b/uts/common/sys/avl.h
@@ -105,6 +105,13 @@ extern "C" {
* as is needed for any linked list implementation.
*/
+/*
+ * AVL comparator helpers
+ */
+#define AVL_ISIGN(a) (((a) > 0) - ((a) < 0))
+#define AVL_CMP(a, b) (((a) > (b)) - ((a) < (b)))
+#define AVL_PCMP(a, b) \
+ (((uintptr_t)(a) > (uintptr_t)(b)) - ((uintptr_t)(a) < (uintptr_t)(b)))
/*
* Type used for the root of the AVL tree.