mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-08 20:22:05 -04:00
A few qp-trie cleanups
Revert refcount debug tracing (commit a8b29f0365), there are better
ways to do it.
Use the dns_qpmethods_t typedef where appropriate.
Some stylistic improvements.
This commit is contained in:
parent
39f38754e2
commit
b3e35fd120
9 changed files with 158 additions and 203 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
62
lib/dns/qp.c
62
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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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] <filename>\n"
|
||||
"usage: qp_dump [-dt] <filename>\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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in a new issue