aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-09-28 18:56:09 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-09-28 18:56:09 +0100
commit07f426c35eddd79388a23d11cb278600d7e3831d (patch)
treebcb98691e7a315c114b3d5102fad981def4e18cd /tests
parent042938f46e1c477419d1931381fdadffaa49d45e (diff)
parent93bf9a42733321fb632bcb9eafd049ef0e3d9417 (diff)
Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20180926' into staging
Queued tcg patches # gpg: Signature made Wed 26 Sep 2018 19:27:22 BST # gpg: using RSA key 64DF38E8AF7E215F # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" # Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F * remotes/rth/tags/pull-tcg-20180926: tcg/i386: fix vector operations on 32-bit hosts qht-bench: add -p flag to precompute hash values qht: constify arguments to some internal functions qht: constify qht_statistics_init qht: constify qht_lookup qht: fix comment in qht_bucket_remove_entry qht: drop ht argument from qht iterators test-qht: speed up + test qht_resize test-qht: test deletion of the last entry in a bucket test-qht: test removal of non-existent entries test-qht: test qht_iter_remove qht: add qht_iter_remove qht: remove unused map param from qht_remove__locked Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests')
-rw-r--r--tests/qht-bench.c26
-rw-r--r--tests/test-qht.c93
2 files changed, 108 insertions, 11 deletions
diff --git a/tests/qht-bench.c b/tests/qht-bench.c
index f492b3a20a..2089e2bed1 100644
--- a/tests/qht-bench.c
+++ b/tests/qht-bench.c
@@ -53,6 +53,7 @@ static unsigned long resize_delay = 1000;
static double resize_rate; /* 0.0 to 1.0 */
static unsigned int n_rz_threads = 1;
static QemuThread *rz_threads;
+static bool precompute_hash;
static double update_rate; /* 0.0 to 1.0 */
static uint64_t update_threshold;
@@ -101,11 +102,18 @@ static bool is_equal(const void *ap, const void *bp)
return *a == *b;
}
-static inline uint32_t h(unsigned long v)
+static uint32_t h(unsigned long v)
{
return tb_hash_func7(v, 0, 0, 0, 0);
}
+static uint32_t hval(unsigned long v)
+{
+ return v;
+}
+
+static uint32_t (*hfunc)(unsigned long v) = h;
+
/*
* From: https://en.wikipedia.org/wiki/Xorshift
* This is faster than rand_r(), and gives us a wider range (RAND_MAX is only
@@ -149,7 +157,7 @@ static void do_rw(struct thread_info *info)
bool read;
p = &keys[info->r & (lookup_range - 1)];
- hash = h(*p);
+ hash = hfunc(*p);
read = qht_lookup(&ht, p, hash);
if (read) {
stats->rd++;
@@ -158,7 +166,7 @@ static void do_rw(struct thread_info *info)
}
} else {
p = &keys[info->r & (update_range - 1)];
- hash = h(*p);
+ hash = hfunc(*p);
if (info->write_op) {
bool written = false;
@@ -289,7 +297,9 @@ static void htable_init(void)
/* avoid allocating memory later by allocating all the keys now */
keys = g_malloc(sizeof(*keys) * n);
for (i = 0; i < n; i++) {
- keys[i] = populate_offset + i;
+ long val = populate_offset + i;
+
+ keys[i] = precompute_hash ? h(val) : hval(val);
}
/* some sanity checks */
@@ -321,7 +331,7 @@ static void htable_init(void)
r = xorshift64star(r);
p = &keys[r & (init_range - 1)];
- hash = h(*p);
+ hash = hfunc(*p);
if (qht_insert(&ht, p, hash, NULL)) {
break;
}
@@ -412,7 +422,7 @@ static void parse_args(int argc, char *argv[])
int c;
for (;;) {
- c = getopt(argc, argv, "d:D:g:k:K:l:hn:N:o:r:Rs:S:u:");
+ c = getopt(argc, argv, "d:D:g:k:K:l:hn:N:o:pr:Rs:S:u:");
if (c < 0) {
break;
}
@@ -451,6 +461,10 @@ static void parse_args(int argc, char *argv[])
case 'o':
populate_offset = atol(optarg);
break;
+ case 'p':
+ precompute_hash = true;
+ hfunc = hval;
+ break;
case 'r':
update_range = pow2ceil(atol(optarg));
break;
diff --git a/tests/test-qht.c b/tests/test-qht.c
index dda6a067be..4d23cefab6 100644
--- a/tests/test-qht.c
+++ b/tests/test-qht.c
@@ -41,7 +41,7 @@ static void insert(int a, int b)
}
}
-static void rm(int init, int end)
+static void do_rm(int init, int end, bool exist)
{
int i;
@@ -49,10 +49,24 @@ static void rm(int init, int end)
uint32_t hash;
hash = arr[i];
- g_assert_true(qht_remove(&ht, &arr[i], hash));
+ if (exist) {
+ g_assert_true(qht_remove(&ht, &arr[i], hash));
+ } else {
+ g_assert_false(qht_remove(&ht, &arr[i], hash));
+ }
}
}
+static void rm(int init, int end)
+{
+ do_rm(init, end, true);
+}
+
+static void rm_nonexist(int init, int end)
+{
+ do_rm(init, end, false);
+}
+
static void check(int a, int b, bool expected)
{
struct qht_stats stats;
@@ -84,7 +98,7 @@ static void check(int a, int b, bool expected)
qht_statistics_destroy(&stats);
}
-static void count_func(struct qht *ht, void *p, uint32_t hash, void *userp)
+static void count_func(void *p, uint32_t hash, void *userp)
{
unsigned int *curr = userp;
@@ -108,14 +122,79 @@ static void iter_check(unsigned int count)
g_assert_cmpuint(curr, ==, count);
}
+static void sum_func(void *p, uint32_t hash, void *userp)
+{
+ uint32_t *sum = userp;
+ uint32_t a = *(uint32_t *)p;
+
+ *sum += a;
+}
+
+static void iter_sum_check(unsigned int expected)
+{
+ unsigned int sum = 0;
+
+ qht_iter(&ht, sum_func, &sum);
+ g_assert_cmpuint(sum, ==, expected);
+}
+
+static bool rm_mod_func(void *p, uint32_t hash, void *userp)
+{
+ uint32_t a = *(uint32_t *)p;
+ unsigned int mod = *(unsigned int *)userp;
+
+ return a % mod == 0;
+}
+
+static void iter_rm_mod(unsigned int mod)
+{
+ qht_iter_remove(&ht, rm_mod_func, &mod);
+}
+
+static void iter_rm_mod_check(unsigned int mod)
+{
+ unsigned int expected = 0;
+ unsigned int i;
+
+ for (i = 0; i < N; i++) {
+ if (i % mod == 0) {
+ continue;
+ }
+ expected += i;
+ }
+ iter_sum_check(expected);
+}
+
static void qht_do_test(unsigned int mode, size_t init_entries)
{
/* under KVM we might fetch stats from an uninitialized qht */
check_n(0);
qht_init(&ht, is_equal, 0, mode);
+ rm_nonexist(0, 4);
+ /*
+ * Test that we successfully delete the last element in a bucket.
+ * This is a hard-to-reach code path when resizing is on, but without
+ * resizing we can easily hit it if init_entries <= 1.
+ * Given that the number of elements per bucket can be 4 or 6 depending on
+ * the host's pointer size, test the removal of the 4th and 6th elements.
+ */
+ insert(0, 4);
+ rm_nonexist(5, 6);
+ rm(3, 4);
+ check_n(3);
+ insert(3, 6);
+ rm(5, 6);
+ check_n(5);
+ rm_nonexist(7, 8);
+ iter_rm_mod(1);
+
+ if (!(mode & QHT_MODE_AUTO_RESIZE)) {
+ qht_resize(&ht, init_entries * 4 + 4);
+ }
check_n(0);
+ rm_nonexist(0, 10);
insert(0, N);
check(0, N, true);
check_n(N);
@@ -138,8 +217,12 @@ static void qht_do_test(unsigned int mode, size_t init_entries)
insert(10, 150);
check_n(N);
- rm(1, 2);
- check_n(N - 1);
+ qht_reset(&ht);
+ insert(0, N);
+ rm_nonexist(N, N + 32);
+ iter_rm_mod(10);
+ iter_rm_mod_check(10);
+ check_n(N * 9 / 10);
qht_reset_size(&ht, 0);
check_n(0);
check(0, N, false);