diff --git a/fuzz/dns_qp.c b/fuzz/dns_qp.c index a528019597..1bc19fa38f 100644 --- a/fuzz/dns_qp.c +++ b/fuzz/dns_qp.c @@ -57,19 +57,18 @@ static struct { dns_qpkey_t ascii; } item[256 * 256 / 4]; -static uint32_t +static void fuzz_attach(void *ctx, void *pval, uint32_t ival) { assert(ctx == NULL); assert(pval == &item[ival]); - return (item[ival].refcount++); + item[ival].refcount++; } -static uint32_t +static void fuzz_detach(void *ctx, void *pval, uint32_t ival) { assert(ctx == NULL); assert(pval == &item[ival]); - assert(item[ival].refcount > 0); - return (item[ival].refcount--); + item[ival].refcount--; } static size_t @@ -86,7 +85,7 @@ fuzz_triename(void *ctx, char *buf, size_t size) { strlcpy(buf, "fuzz", size); } -const struct dns_qpmethods fuzz_methods = { +const dns_qpmethods_t fuzz_methods = { fuzz_attach, fuzz_detach, fuzz_makekey, diff --git a/lib/dns/include/dns/qp.h b/lib/dns/include/dns/qp.h index 09da5ad1a5..a425a4c257 100644 --- a/lib/dns/include/dns/qp.h +++ b/lib/dns/include/dns/qp.h @@ -109,7 +109,9 @@ typedef struct dns_qpmulti dns_qpmulti_t; * Read-only parts of a qp-trie. * * A `dns_qpreader_t` is the common prefix of the `dns_qpreadable` - * types, containing just the fields neded for the hot path. + * types, containing just the fields neded for the hot path. The + * internals of a `dns_qpreader_t` are private; they are only exposed + * so that callers can allocate a `dns_qpread_t` on the stack. * * Ranty aside: annoyingly, C doesn't allow us to use a predeclared * structure type as an anonymous struct member, so we have to use a @@ -135,6 +137,9 @@ typedef struct dns_qpreader { * The caller provides space for it on the stack; it can be * used by only one thread. As well as the `DNS_QPREADER_FIELDS`, * it contains a thread ID to check for incorrect usage. + * + * The internals of a `dns_qpread_t` are private; they are only + * exposed so that callers can allocate an instance on the stack. */ typedef struct dns_qpread { DNS_QPREADER_FIELDS; @@ -209,9 +214,7 @@ typedef struct dns_qpiter { * The `attach` and `detach` methods adjust reference counts on value * objects. They support copy-on-write and safe memory reclamation * needed for multi-version concurrency. The methods are only called - * when the `dns_qpmulti_t` mutex is held. For tracing purposes, they - * should return the same value as `isc_refcount_increment()` or - * `isc_refcount_decrement()`, respectively + * when the `dns_qpmulti_t` mutex is held. * * Note: When a value object reference count is greater than one, the * object is in use by concurrent readers so it must not be modified. A @@ -230,8 +233,8 @@ typedef struct dns_qpiter { * readable identifier into `buf` which has max length `size`. */ typedef struct dns_qpmethods { - uint32_t (*attach)(void *uctx, void *pval, uint32_t ival); - uint32_t (*detach)(void *uctx, void *pval, uint32_t ival); + void (*attach)(void *uctx, void *pval, uint32_t ival); + void (*detach)(void *uctx, void *pval, uint32_t ival); size_t (*makekey)(dns_qpkey_t key, void *uctx, void *pval, uint32_t ival); void (*triename)(void *uctx, char *buf, size_t size); diff --git a/lib/dns/qp.c b/lib/dns/qp.c index 881b68ec9a..60acf13ed5 100644 --- a/lib/dns/qp.c +++ b/lib/dns/qp.c @@ -482,6 +482,7 @@ static inline qp_ref_t alloc_twigs(dns_qp_t *qp, qp_weight_t size) { qp_chunk_t chunk = qp->bump; qp_cell_t cell = qp->usage[chunk].used; + if (cell + size <= QP_CHUNK_SIZE) { qp->usage[chunk].used += size; qp->used_count += size; @@ -843,6 +844,7 @@ compact_recursive(dns_qp_t *qp, qp_node_t *parent) { qp_weight_t size = branch_twigs_size(parent); qp_ref_t twigs_ref = branch_twigs_ref(parent); qp_chunk_t chunk = ref_chunk(twigs_ref); + if (qp->compact_all || (chunk != qp->bump && chunk_usage(qp, chunk) < QP_MIN_USED)) { @@ -1027,15 +1029,12 @@ dns_qp_gctime(isc_nanosecs_t *compact_p, isc_nanosecs_t *recycle_p, static dns_qp_t * transaction_open(dns_qpmulti_t *multi, dns_qp_t **qptp) { - dns_qp_t *qp; - REQUIRE(QPMULTI_VALID(multi)); REQUIRE(qptp != NULL && *qptp == NULL); LOCK(&multi->mutex); - qp = &multi->writer; - + dns_qp_t *qp = &multi->writer; INSIST(QP_VALID(qp)); /* @@ -1396,11 +1395,9 @@ dns_qpsnap_destroy(dns_qpmulti_t *multi, dns_qpsnap_t **qpsp) { void dns_qp_create(isc_mem_t *mctx, const dns_qpmethods_t *methods, void *uctx, dns_qp_t **qptp) { - dns_qp_t *qp; - REQUIRE(qptp != NULL && *qptp == NULL); - qp = isc_mem_get(mctx, sizeof(*qp)); + dns_qp_t *qp = isc_mem_get(mctx, sizeof(*qp)); QP_INIT(qp, methods, uctx); isc_mem_attach(mctx, &qp->mctx); alloc_reset(qp); @@ -1412,12 +1409,9 @@ void dns_qpmulti_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr, const dns_qpmethods_t *methods, void *uctx, dns_qpmulti_t **qpmp) { - dns_qpmulti_t *multi; - dns_qp_t *qp; - REQUIRE(qpmp != NULL && *qpmp == NULL); - multi = isc_mem_get(mctx, sizeof(*multi)); + dns_qpmulti_t *multi = isc_mem_get(mctx, sizeof(*multi)); *multi = (dns_qpmulti_t){ .magic = QPMULTI_MAGIC, .reader_ref = INVALID_REF, @@ -1432,7 +1426,7 @@ dns_qpmulti_create(isc_mem_t *mctx, isc_loopmgr_t *loopmgr, * allocates; to ensure dns_qpmulti_write() does too, pretend the * previous transaction was an update */ - qp = &multi->writer; + dns_qp_t *qp = &multi->writer; QP_INIT(qp, methods, uctx); isc_mem_attach(mctx, &qp->mctx); qp->transaction_mode = QP_UPDATE; @@ -1460,12 +1454,10 @@ destroy_guts(dns_qp_t *qp) { void dns_qp_destroy(dns_qp_t **qptp) { - dns_qp_t *qp; - REQUIRE(qptp != NULL); REQUIRE(QP_VALID(*qptp)); - qp = *qptp; + dns_qp_t *qp = *qptp; *qptp = NULL; /* do not try to destroy part of a dns_qpmulti_t */ @@ -1478,14 +1470,11 @@ dns_qp_destroy(dns_qp_t **qptp) { void dns_qpmulti_destroy(dns_qpmulti_t **qpmp) { - dns_qp_t *qp = NULL; - dns_qpmulti_t *multi = NULL; - REQUIRE(qpmp != NULL); REQUIRE(QPMULTI_VALID(*qpmp)); - multi = *qpmp; - qp = &multi->writer; + dns_qpmulti_t *multi = *qpmp; + dns_qp_t *qp = &multi->writer; *qpmp = NULL; REQUIRE(QP_VALID(qp)); @@ -1513,7 +1502,7 @@ isc_result_t dns_qp_insert(dns_qp_t *qp, void *pval, uint32_t ival) { qp_ref_t new_ref, old_ref; qp_node_t new_leaf, old_node; - qp_node_t *new_twigs, *old_twigs; + qp_node_t *new_twigs = NULL, *old_twigs = NULL; qp_shift_t new_bit, old_bit; qp_weight_t old_size, new_size; dns_qpkey_t new_key, old_key; @@ -1522,7 +1511,7 @@ dns_qp_insert(dns_qp_t *qp, void *pval, uint32_t ival) { uint64_t index; qp_shift_t bit; qp_weight_t pos; - qp_node_t *n; + qp_node_t *n = NULL; REQUIRE(QP_VALID(qp)); @@ -1639,15 +1628,6 @@ growbranch: isc_result_t dns_qp_deletekey(dns_qp_t *qp, const dns_qpkey_t search_key, size_t search_keylen) { - dns_qpkey_t found_key; - size_t found_keylen; - qp_shift_t bit = 0; /* suppress warning */ - qp_weight_t pos, size; - qp_ref_t ref; - qp_node_t *twigs; - qp_node_t *parent; - qp_node_t *n; - REQUIRE(QP_VALID(qp)); REQUIRE(search_keylen < sizeof(dns_qpkey_t)); @@ -1655,8 +1635,9 @@ dns_qp_deletekey(dns_qp_t *qp, const dns_qpkey_t search_key, return (ISC_R_NOTFOUND); } - parent = NULL; - n = make_root_mutable(qp); + qp_shift_t bit = 0; /* suppress warning */ + qp_node_t *parent = NULL; + qp_node_t *n = make_root_mutable(qp); while (is_branch(n)) { prefetch_twigs(qp, n); bit = branch_keybit(n, search_key, search_keylen); @@ -1668,7 +1649,8 @@ dns_qp_deletekey(dns_qp_t *qp, const dns_qpkey_t search_key, n = branch_twig_ptr(qp, n, bit); } - found_keylen = leaf_qpkey(qp, n, found_key); + dns_qpkey_t found_key; + size_t found_keylen = leaf_qpkey(qp, n, found_key); if (qpkey_compare(search_key, search_keylen, found_key, found_keylen) != QPKEY_EQUAL) { @@ -1692,10 +1674,10 @@ dns_qp_deletekey(dns_qp_t *qp, const dns_qpkey_t search_key, parent = NULL; INSIST(bit != 0); - size = branch_twigs_size(n); - pos = branch_twig_pos(n, bit); - ref = branch_twigs_ref(n); - twigs = ref_ptr(qp, ref); + qp_weight_t size = branch_twigs_size(n); + qp_weight_t pos = branch_twig_pos(n, bit); + qp_ref_t ref = branch_twigs_ref(n); + qp_node_t *twigs = ref_ptr(qp, ref); if (size == 2) { /* @@ -1801,7 +1783,7 @@ dns_qp_getkey(dns_qpreadable_t qpr, const dns_qpkey_t search_key, dns_qpkey_t found_key; size_t found_keylen; qp_shift_t bit; - qp_node_t *n; + qp_node_t *n = NULL; REQUIRE(QP_VALID(qp)); REQUIRE(pval_r != NULL); @@ -1850,7 +1832,7 @@ dns_qp_findname_parent(dns_qpreadable_t qpr, const dns_name_t *name, size_t searchlen, foundlen; size_t offset; qp_shift_t bit; - qp_node_t *n, *twigs; + qp_node_t *n = NULL, *twigs = NULL; isc_result_t result; unsigned int labels = 0; struct offref { diff --git a/lib/dns/qp_p.h b/lib/dns/qp_p.h index 12029e72c2..90d05a20d8 100644 --- a/lib/dns/qp_p.h +++ b/lib/dns/qp_p.h @@ -894,34 +894,6 @@ unpack_reader(dns_qpreader_t *qp, qp_node_t *reader) { * method invocation helpers */ -#if 0 - -#define attach_leaf(qp, n) \ - do { \ - uint32_t iv = leaf_ival(n); \ - void *pv = leaf_pval(n); \ - uint32_t r = qp->methods->attach(qp->uctx, pv, iv); \ - fprintf(stderr, \ - "%s:%u:%s():t%u qp %p node %p leaf %p %u " \ - "(%u -> %u)\n", \ - __FILE__, __LINE__, __func__, isc_tid(), qp, n, pv, \ - iv, r, r + 1); \ - } while (0) - -#define detach_leaf(qp, n) \ - do { \ - uint32_t iv = leaf_ival(n); \ - void *pv = leaf_pval(n); \ - uint32_t r = qp->methods->detach(qp->uctx, pv, iv); \ - fprintf(stderr, \ - "%s:%u:%s():t%u qp %p node %p leaf %p %u " \ - "(%u -> %u)\n", \ - __FILE__, __LINE__, __func__, isc_tid(), qp, n, pv, \ - iv, r, r - 1); \ - } while (0) - -#else - static inline void attach_leaf(dns_qpreadable_t qpr, qp_node_t *n) { dns_qpreader_t *qp = dns_qpreader(qpr); @@ -934,8 +906,6 @@ detach_leaf(dns_qpreadable_t qpr, qp_node_t *n) { qp->methods->detach(qp->uctx, leaf_pval(n), leaf_ival(n)); } -#endif - static inline size_t leaf_qpkey(dns_qpreadable_t qpr, qp_node_t *n, dns_qpkey_t key) { dns_qpreader_t *qp = dns_qpreader(qpr); diff --git a/tests/bench/load-names.c b/tests/bench/load-names.c index f7d5aa79d2..babdd37ef1 100644 --- a/tests/bench/load-names.c +++ b/tests/bench/load-names.c @@ -37,11 +37,10 @@ struct { dns_fixedname_t fixed; } item[1024 * 1024]; -static uint32_t +static void item_check(void *ctx, void *pval, uint32_t ival) { UNUSED(ctx); assert(pval == &item[ival]); - return (1); } static size_t @@ -57,7 +56,7 @@ testname(void *ctx, char *buf, size_t size) { strlcpy(buf, "test", size); } -const struct dns_qpmethods qpmethods = { +const dns_qpmethods_t qpmethods = { item_check, item_check, item_makekey, @@ -201,7 +200,7 @@ static struct fun { #define FILE_CHECK(check, msg) \ do { \ if (!(check)) { \ - fprintf(stderr, "%s:%zu: %s\n", filename, count, msg); \ + fprintf(stderr, "%s:%zu: %s\n", filename, lines, msg); \ exit(1); \ } \ } while (0) @@ -209,6 +208,12 @@ static struct fun { int main(int argc, char *argv[]) { isc_result_t result; + const char *filename = NULL; + char *filetext = NULL; + off_t fileoff; + FILE *fp = NULL; + size_t filesize, lines = 0, wirebytes = 0, labels = 0; + char *pos = NULL, *file_end = NULL; isc_mem_create(&mctx); @@ -217,18 +222,17 @@ main(int argc, char *argv[]) { exit(1); } - const char *filename = argv[1]; - off_t fileoff; + filename = argv[1]; result = isc_file_getsize(filename, &fileoff); if (result != ISC_R_SUCCESS) { fprintf(stderr, "stat(%s): %s\n", filename, isc_result_totext(result)); exit(1); } - size_t filesize = (size_t)fileoff; + filesize = (size_t)fileoff; - char *filetext = isc_mem_get(mctx, filesize + 1); - FILE *fp = fopen(filename, "r"); + filetext = isc_mem_get(mctx, filesize + 1); + fp = fopen(filename, "r"); if (fp == NULL || fread(filetext, 1, filesize, fp) < filesize) { fprintf(stderr, "read(%s): %s\n", filename, strerror(errno)); exit(1); @@ -236,29 +240,28 @@ main(int argc, char *argv[]) { fclose(fp); filetext[filesize] = '\0'; - size_t count = 0; - size_t wirebytes = 0; - size_t labels = 0; - - char *pos = filetext; - char *file_end = pos + filesize; + pos = filetext; + file_end = pos + filesize; while (pos < file_end) { - FILE_CHECK(count < ARRAY_SIZE(item), "too many lines"); + char *domain = NULL, *newline = NULL; + size_t len; + + FILE_CHECK(lines < ARRAY_SIZE(item), "too many lines"); pos += strspn(pos, "0123456789"); FILE_CHECK(*pos++ == ',', "missing comma"); - char *domain = pos; + domain = pos; pos += strcspn(pos, "\r\n"); FILE_CHECK(*pos != '\0', "missing newline"); - char *newline = pos; + newline = pos; pos += strspn(pos, "\r\n"); - size_t len = newline - domain; + len = newline - domain; - item[count].text = domain; + item[lines].text = domain; domain[len] = '\0'; - dns_name_t *name = dns_fixedname_initname(&item[count].fixed); + dns_name_t *name = dns_fixedname_initname(&item[lines].fixed); isc_buffer_t buffer; isc_buffer_init(&buffer, domain, len); isc_buffer_add(&buffer, len); @@ -268,41 +271,35 @@ main(int argc, char *argv[]) { wirebytes += name->length; labels += name->labels; - count++; + lines++; } printf("names %g MB labels %g MB\n", (double)wirebytes / 1048576.0, (double)labels / 1048576.0); - size_t lines = count; - for (struct fun *fun = fun_list; fun->name != NULL; fun++) { - isc_time_t t0; - t0 = isc_time_now_hires(); - isc_mem_t *mem = NULL; - isc_mem_create(&mem); - void *map = fun->new (mem); + void *map = NULL; - for (count = 0; count < lines; count++) { - result = fun->add(map, count); + isc_mem_create(&mem); + map = fun->new (mem); + + isc_time_t t0 = isc_time_now_hires(); + for (size_t n = 0; n < lines; n++) { + result = fun->add(map, n); CHECK(result); } fun->sqz(map); - isc_time_t t1; - t1 = isc_time_now_hires(); - - for (count = 0; count < lines; count++) { + isc_time_t t1 = isc_time_now_hires(); + for (size_t n = 0; n < lines; n++) { void *pval = NULL; - result = fun->get(map, count, &pval); + result = fun->get(map, n, &pval); CHECK(result); - assert(pval == &item[count]); + assert(pval == &item[n]); } - isc_time_t t2; - t2 = isc_time_now_hires(); - + isc_time_t t2 = isc_time_now_hires(); printf("%f sec to load %s\n", (double)isc_time_microdiff(&t1, &t0) / (1000.0 * 1000.0), fun->name); diff --git a/tests/bench/qp-dump.c b/tests/bench/qp-dump.c index 9cf72c1661..855bbbc3dc 100644 --- a/tests/bench/qp-dump.c +++ b/tests/bench/qp-dump.c @@ -95,19 +95,17 @@ qpkey_from_smallname(dns_qpkey_t key, void *ctx, void *pval, uint32_t ival) { return (dns_qpkey_fromname(key, &name)); } -static uint32_t +static void smallname_attach(void *ctx, void *pval, uint32_t ival) { UNUSED(ctx); - return (isc_refcount_increment0(smallname_refcount(pval, ival))); + isc_refcount_increment0(smallname_refcount(pval, ival)); } -static uint32_t +static void smallname_detach(void *ctx, void *pval, uint32_t ival) { - uint32_t refs = isc_refcount_decrement(smallname_refcount(pval, ival)); - if (refs == 1) { + if (isc_refcount_decrement(smallname_refcount(pval, ival)) == 1) { isc_mem_free(ctx, pval); } - return (refs); } static void @@ -116,7 +114,7 @@ testname(void *ctx, char *buf, size_t size) { strlcpy(buf, "test", size); } -const struct dns_qpmethods methods = { +const dns_qpmethods_t methods = { smallname_attach, smallname_detach, qpkey_from_smallname, @@ -126,15 +124,23 @@ const struct dns_qpmethods methods = { static void usage(void) { fprintf(stderr, - "usage: qp_dump [-drt] \n" + "usage: qp_dump [-dt] \n" " -d output in graphviz dot format\n" " -t output in ad-hoc indented text format\n"); } int main(int argc, char *argv[]) { - bool dumpdot = false; - bool dumptxt = false; + isc_result_t result; + dns_qp_t *qp = NULL; + const char *filename = NULL; + char *filetext = NULL; + size_t filesize; + off_t fileoff; + FILE *fp = NULL; + size_t wirebytes = 0, labels = 0, names = 0; + char *pos = NULL, *file_end = NULL; + bool dumpdot = false, dumptxt = false; int opt; while ((opt = isc_commandline_parse(argc, argv, "dt")) != -1) { @@ -162,18 +168,17 @@ main(int argc, char *argv[]) { isc_mem_create(&mctx); - const char *filename = argv[0]; - off_t fileoff; - isc_result_t result = isc_file_getsize(filename, &fileoff); + filename = argv[0]; + result = isc_file_getsize(filename, &fileoff); if (result != ISC_R_SUCCESS) { fprintf(stderr, "stat(%s): %s\n", filename, isc_result_totext(result)); exit(1); } - size_t filesize = (size_t)fileoff; - char *filetext = isc_mem_get(mctx, filesize + 1); - FILE *fp = fopen(filename, "r"); + filesize = (size_t)fileoff; + filetext = isc_mem_get(mctx, filesize + 1); + fp = fopen(filename, "r"); if (fp == NULL || fread(filetext, 1, filesize, fp) < filesize) { fprintf(stderr, "read(%s): %s\n", filename, strerror(errno)); exit(1); @@ -181,31 +186,30 @@ main(int argc, char *argv[]) { fclose(fp); filetext[filesize] = '\0'; - dns_qp_t *qp = NULL; dns_qp_create(mctx, &methods, NULL, &qp); - size_t wirebytes = 0; - size_t labels = 0; - size_t names = 0; - char *pos = filetext; - char *file_end = pos + filesize; + pos = filetext; + file_end = pos + filesize; while (pos < file_end) { - char *domain = pos; - pos += strcspn(pos, "\r\n"); - char *newline = pos; - pos += strspn(pos, "\r\n"); - size_t len = newline - domain; - domain[len] = '\0'; - + void *pval = NULL; + uint32_t ival = 0; dns_fixedname_t fixed; dns_name_t *name = dns_fixedname_initname(&fixed); isc_buffer_t buffer; + char *newline = NULL, *domain = pos; + size_t len; + + pos += strcspn(pos, "\r\n"); + newline = pos; + pos += strspn(pos, "\r\n"); + + len = newline - domain; + domain[len] = '\0'; + isc_buffer_init(&buffer, domain, len); isc_buffer_add(&buffer, len); result = dns_name_fromtext(name, &buffer, dns_rootname, 0, NULL); - void *pval = NULL; - uint32_t ival = 0; if (result == ISC_R_SUCCESS) { smallname_from_name(name, &pval, &ival); result = dns_qp_insert(qp, pval, ival); @@ -226,15 +230,16 @@ main(int argc, char *argv[]) { } dns_qp_compact(qp, DNS_QPGC_ALL); - size_t smallbytes = wirebytes + labels + names * sizeof(isc_refcount_t); - dns_qp_memusage_t memusage = dns_qp_memusage(qp); - uint64_t compaction_us, recovery_us, rollback_us; - dns_qp_gctime(&compaction_us, &recovery_us, &rollback_us); - #define print_megabytes(label, value) \ printf("%6.2f MiB - " label "\n", (double)(value) / 1048576.0) if (!dumptxt && !dumpdot) { + size_t smallbytes = wirebytes + labels + + names * sizeof(isc_refcount_t); + dns_qp_memusage_t memusage = dns_qp_memusage(qp); + uint64_t compaction_us, recovery_us, rollback_us; + dns_qp_gctime(&compaction_us, &recovery_us, &rollback_us); + printf("leaves %zu\n" " nodes %zu\n" " used %zu\n" @@ -264,10 +269,12 @@ main(int argc, char *argv[]) { printf("%6zu - max key len\n", qp_test_maxkeylen(qp)); } - if (dumptxt) + if (dumptxt) { qp_test_dumptrie(qp); - if (dumpdot) + } + if (dumpdot) { qp_test_dumpdot(qp); + } return (0); } diff --git a/tests/bench/qpmulti.c b/tests/bench/qpmulti.c index f6150024a9..7034ac983f 100644 --- a/tests/bench/qpmulti.c +++ b/tests/bench/qpmulti.c @@ -89,12 +89,11 @@ static struct { dns_qpkey_t key; } *item; -static uint32_t +static void item_refcount(void *ctx, void *pval, uint32_t ival) { UNUSED(ctx); UNUSED(pval); UNUSED(ival); - return (1); } static size_t @@ -111,7 +110,7 @@ benchname(void *ctx, char *buf, size_t size) { strlcpy(buf, "bench", size); } -const struct dns_qpmethods item_methods = { +const dns_qpmethods_t item_methods = { item_refcount, item_refcount, item_makekey, @@ -128,13 +127,12 @@ init_items(isc_mem_t *mctx) { void *pval = NULL; uint32_t ival = ~0U; dns_qp_t *qp = NULL; - size_t bytes = ITEM_COUNT * sizeof(*item); + uint64_t start; + start = isc_time_monotonic(); item = isc_mem_allocatex(mctx, bytes, ISC_MEM_ZERO); - uint64_t start = isc_time_monotonic(); - /* ensure there are no duplicate names */ dns_qp_create(mctx, &item_methods, NULL, &qp); for (size_t i = 0; i < ITEM_COUNT; i++) { @@ -224,6 +222,7 @@ first_loop(void *varg) { static void next_loop(struct thread_args *args, isc_nanosecs_t start) { isc_nanosecs_t stop = isc_time_monotonic(); + args->worked += stop - start; args->stop = stop; if (args->stop - args->start < RUNTIME) { @@ -238,6 +237,9 @@ next_loop(struct thread_args *args, isc_nanosecs_t start) { static void read_zipf(uv_idle_t *idle) { struct thread_args *args = idle->data; + isc_nanosecs_t start; + void *pval = NULL; + uint32_t ival; /* outside time because it is v slow */ uint32_t r[args->tx_per_loop][args->ops_per_tx]; @@ -247,10 +249,7 @@ read_zipf(uv_idle_t *idle) { } } - isc_nanosecs_t start = isc_time_monotonic(); - void *pval; - uint32_t ival; - + start = isc_time_monotonic(); for (uint32_t tx = 0; tx < args->tx_per_loop; tx++) { args->transactions++; dns_qpread_t qp; @@ -277,7 +276,7 @@ static void read_transactions(uv_idle_t *idle) { struct thread_args *args = idle->data; isc_nanosecs_t start = isc_time_monotonic(); - void *pval; + void *pval = NULL; uint32_t ival; for (uint32_t tx = 0; tx < args->tx_per_loop; tx++) { @@ -379,13 +378,13 @@ static void load_multi(struct bench_state *bctx) { dns_qp_t *qp = NULL; size_t count = 0; - - uint64_t start = isc_time_monotonic(); + uint64_t start; dns_qpmulti_create(bctx->mctx, bctx->loopmgr, &item_methods, NULL, &bctx->multi); /* initial contents of the trie */ + start = isc_time_monotonic(); dns_qpmulti_update(bctx->multi, &qp); for (size_t i = 0; i < bctx->max_item; i++) { if (isc_random_uniform(2) == 0) { @@ -745,11 +744,18 @@ dispatch(struct bench_state *bctx) { static void collect(void *varg) { - TRACE(""); - struct thread_args *args = varg; struct bench_state *bctx = args->bctx; struct thread_args *thread = bctx->thread; + struct { + uint64_t worked, txns, ops, compactions; + } stats[2] = {}; + double load_time = bctx->load_time; + double elapsed = 0, mut_work, readers, read_work, elapsed_ms; + uint32_t nloops; + bool zipf; + + TRACE("collect"); bctx->waiting--; if (bctx->waiting > 0) { @@ -757,20 +763,15 @@ collect(void *varg) { } isc_barrier_destroy(&bctx->barrier); - struct { - uint64_t worked, txns, ops, compactions; - } stats[2] = {}; - - double load_time = bctx->load_time; load_time = load_time > 0 ? load_time / (double)NS_PER_SEC : NAN; - double elapsed = 0; - bool zipf = bctx->mutate == 0 && bctx->readers == 0; - uint32_t nloops = zipf ? bctx->nloops : bctx->readers + bctx->mutate; + zipf = bctx->mutate == 0 && bctx->readers == 0; + nloops = zipf ? bctx->nloops : bctx->readers + bctx->mutate; for (uint32_t t = 0; t < nloops; t++) { struct thread_args *tp = &thread[t]; elapsed = ISC_MAX(elapsed, (tp->stop - tp->start)); bool mut = t < bctx->mutate; + stats[mut].worked += tp->worked; stats[mut].txns += tp->transactions; stats[mut].ops += tp->transactions * tp->ops_per_tx; @@ -783,7 +784,7 @@ collect(void *varg) { printf("%7.2f\t", (double)bctx->qp_bytes / bctx->qp_items); printf("%7u\t", bctx->max_item); - double mut_work = stats[1].worked / (double)US_PER_MS; + mut_work = stats[1].worked / (double)US_PER_MS; printf("%7u\t", bctx->mutate); printf("%7u\t", bctx->mut_tx_per_loop); printf("%7u\t", bctx->mut_ops_per_tx); @@ -794,9 +795,9 @@ collect(void *varg) { printf("%7.2f\t", stats[1].txns / mut_work); printf("%7.2f\t", stats[1].ops / mut_work); - double readers = zipf ? bctx->nloops - bctx->mutate : bctx->readers; - double read_work = stats[0].worked / (double)US_PER_MS; - double elapsed_ms = elapsed / (double)US_PER_MS; + readers = zipf ? bctx->nloops - bctx->mutate : bctx->readers; + read_work = stats[0].worked / (double)US_PER_MS; + elapsed_ms = elapsed / (double)US_PER_MS; printf("%7u\t", bctx->readers); printf("%7u\t", bctx->read_tx_per_loop); printf("%7u\t", bctx->read_ops_per_tx); @@ -817,10 +818,8 @@ startup(void *arg) { isc_loop_t *loop = isc_loop_current(loopmgr); isc_mem_t *mctx = isc_loop_getmctx(loop); uint32_t nloops = isc_loopmgr_nloops(loopmgr); - size_t bytes = sizeof(struct bench_state) + sizeof(struct thread_args) * nloops; - struct bench_state *bctx = isc_mem_getx(mctx, bytes, ISC_MEM_ZERO); *bctx = (struct bench_state){ @@ -885,9 +884,9 @@ int main(void) { isc_loopmgr_t *loopmgr = NULL; isc_mem_t *mctx = NULL; - uint32_t nloops; const char *env_workers = getenv("ISC_TASK_WORKERS"); + if (env_workers != NULL) { nloops = atoi(env_workers); } else { diff --git a/tests/dns/qp_test.c b/tests/dns/qp_test.c index 9391804b15..ee9b30da00 100644 --- a/tests/dns/qp_test.c +++ b/tests/dns/qp_test.c @@ -136,12 +136,11 @@ ISC_RUN_TEST_IMPL(qpkey_sort) { #define ITER_ITEMS 100 -static uint32_t +static void check_leaf(void *uctx, void *pval, uint32_t ival) { uint32_t *items = uctx; assert_in_range(ival, 1, ITER_ITEMS - 1); assert_ptr_equal(items + ival, pval); - return (1); } static size_t @@ -168,7 +167,7 @@ getname(void *uctx, char *buf, size_t size) { UNUSED(size); } -const struct dns_qpmethods qpiter_methods = { +const dns_qpmethods_t qpiter_methods = { check_leaf, check_leaf, qpiter_makekey, @@ -216,12 +215,11 @@ ISC_RUN_TEST_IMPL(qpiter) { dns_qp_destroy(&qp); } -static uint32_t +static void no_op(void *uctx, void *pval, uint32_t ival) { UNUSED(uctx); UNUSED(pval); UNUSED(ival); - return (1); } static size_t @@ -237,7 +235,7 @@ qpkey_fromstring(dns_qpkey_t key, void *uctx, void *pval, uint32_t ival) { return (dns_qpkey_fromname(key, dns_fixedname_name(&fixed))); } -const struct dns_qpmethods string_methods = { +const dns_qpmethods_t string_methods = { no_op, no_op, qpkey_fromstring, diff --git a/tests/dns/qpmulti_test.c b/tests/dns/qpmulti_test.c index 28605080e0..16e5350dec 100644 --- a/tests/dns/qpmulti_test.c +++ b/tests/dns/qpmulti_test.c @@ -104,19 +104,19 @@ static struct { dns_qpkey_t ascii; } item[ITEM_COUNT]; -static uint32_t +static void item_attach(void *ctx, void *pval, uint32_t ival) { - assert_null(ctx); - assert_ptr_equal(pval, &item[ival]); - return (item[ival].refcount++); + INSIST(ctx == NULL); + INSIST(pval == &item[ival]); + item[ival].refcount++; } -static uint32_t +static void item_detach(void *ctx, void *pval, uint32_t ival) { assert_null(ctx); assert_ptr_equal(pval, &item[ival]); assert_int_not_equal(item[ival].refcount, 0); - return (item[ival].refcount--); + item[ival].refcount--; } static size_t @@ -144,7 +144,7 @@ testname(void *ctx, char *buf, size_t size) { strlcpy(buf, "test", size); } -const struct dns_qpmethods test_methods = { +const dns_qpmethods_t test_methods = { item_attach, item_detach, item_makekey,