- speed up unbound (reports say it could be up to 10%), by reducing

lock contention on localzones.lock.  It is changed to an rwlock.


git-svn-id: file:///svn/unbound/trunk@3048 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2014-01-24 11:21:15 +00:00
parent 9a1e15776f
commit 1a24208658
5 changed files with 48 additions and 44 deletions

View file

@ -981,7 +981,7 @@ do_zone_add(SSL* ssl, struct worker* worker, char* arg)
free(nm);
return;
}
lock_quick_lock(&worker->daemon->local_zones->lock);
lock_rw_wrlock(&worker->daemon->local_zones->lock);
if((z=local_zones_find(worker->daemon->local_zones, nm, nmlen,
nmlabs, LDNS_RR_CLASS_IN))) {
/* already present in tree */
@ -989,17 +989,17 @@ do_zone_add(SSL* ssl, struct worker* worker, char* arg)
z->type = t; /* update type anyway */
lock_rw_unlock(&z->lock);
free(nm);
lock_quick_unlock(&worker->daemon->local_zones->lock);
lock_rw_unlock(&worker->daemon->local_zones->lock);
send_ok(ssl);
return;
}
if(!local_zones_add_zone(worker->daemon->local_zones, nm, nmlen,
nmlabs, LDNS_RR_CLASS_IN, t)) {
lock_quick_unlock(&worker->daemon->local_zones->lock);
lock_rw_unlock(&worker->daemon->local_zones->lock);
ssl_printf(ssl, "error out of memory\n");
return;
}
lock_quick_unlock(&worker->daemon->local_zones->lock);
lock_rw_unlock(&worker->daemon->local_zones->lock);
send_ok(ssl);
}
@ -1013,13 +1013,13 @@ do_zone_remove(SSL* ssl, struct worker* worker, char* arg)
struct local_zone* z;
if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs))
return;
lock_quick_lock(&worker->daemon->local_zones->lock);
lock_rw_wrlock(&worker->daemon->local_zones->lock);
if((z=local_zones_find(worker->daemon->local_zones, nm, nmlen,
nmlabs, LDNS_RR_CLASS_IN))) {
/* present in tree */
local_zones_del_zone(worker->daemon->local_zones, z);
}
lock_quick_unlock(&worker->daemon->local_zones->lock);
lock_rw_unlock(&worker->daemon->local_zones->lock);
free(nm);
send_ok(ssl);
}
@ -1974,7 +1974,7 @@ do_list_local_zones(SSL* ssl, struct worker* worker)
struct local_zones* zones = worker->daemon->local_zones;
struct local_zone* z;
char buf[257];
lock_quick_lock(&zones->lock);
lock_rw_rdlock(&zones->lock);
RBTREE_FOR(z, struct local_zone*, &zones->ztree) {
lock_rw_rdlock(&z->lock);
dname_str(z->name, buf);
@ -1982,7 +1982,7 @@ do_list_local_zones(SSL* ssl, struct worker* worker)
local_zone_type2str(z->type));
lock_rw_unlock(&z->lock);
}
lock_quick_unlock(&zones->lock);
lock_rw_unlock(&zones->lock);
}
/** do the list_local_data command */
@ -1995,7 +1995,7 @@ do_list_local_data(SSL* ssl, struct worker* worker)
struct local_rrset* p;
char* s = (char*)sldns_buffer_begin(worker->env.scratch_buffer);
size_t slen = sldns_buffer_capacity(worker->env.scratch_buffer);
lock_quick_lock(&zones->lock);
lock_rw_rdlock(&zones->lock);
RBTREE_FOR(z, struct local_zone*, &zones->ztree) {
lock_rw_rdlock(&z->lock);
RBTREE_FOR(d, struct local_data*, &z->data) {
@ -2016,7 +2016,7 @@ do_list_local_data(SSL* ssl, struct worker* worker)
}
lock_rw_unlock(&z->lock);
}
lock_quick_unlock(&zones->lock);
lock_rw_unlock(&zones->lock);
}
/** tell other processes to execute the command */

View file

@ -2,6 +2,8 @@
- Change unbound-event.h to use void* buffer, length idiom.
- iana portlist updated.
- unbound-event.h is installed if you configure --enable-event-api.
- speed up unbound (reports say it could be up to 10%), by reducing
lock contention on localzones.lock. It is changed to an rwlock.
21 January 2014: Wouter
- Fix #547: no trustanchor written if filesystem full, fclose checked.

View file

@ -1125,23 +1125,23 @@ int ub_ctx_zone_add(struct ub_ctx* ctx, const char *zone_name,
return UB_SYNTAX;
}
lock_quick_lock(&ctx->local_zones->lock);
lock_rw_wrlock(&ctx->local_zones->lock);
if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs,
LDNS_RR_CLASS_IN))) {
/* already present in tree */
lock_rw_wrlock(&z->lock);
z->type = t; /* update type anyway */
lock_rw_unlock(&z->lock);
lock_quick_unlock(&ctx->local_zones->lock);
lock_rw_unlock(&ctx->local_zones->lock);
free(nm);
return UB_NOERROR;
}
if(!local_zones_add_zone(ctx->local_zones, nm, nmlen, nmlabs,
LDNS_RR_CLASS_IN, t)) {
lock_quick_unlock(&ctx->local_zones->lock);
lock_rw_unlock(&ctx->local_zones->lock);
return UB_NOMEM;
}
lock_quick_unlock(&ctx->local_zones->lock);
lock_rw_unlock(&ctx->local_zones->lock);
return UB_NOERROR;
}
@ -1160,13 +1160,13 @@ int ub_ctx_zone_remove(struct ub_ctx* ctx, const char *zone_name)
return UB_SYNTAX;
}
lock_quick_lock(&ctx->local_zones->lock);
lock_rw_wrlock(&ctx->local_zones->lock);
if((z=local_zones_find(ctx->local_zones, nm, nmlen, nmlabs,
LDNS_RR_CLASS_IN))) {
/* present in tree */
local_zones_del_zone(ctx->local_zones, z);
}
lock_quick_unlock(&ctx->local_zones->lock);
lock_rw_unlock(&ctx->local_zones->lock);
free(nm);
return UB_NOERROR;
}

View file

@ -59,7 +59,7 @@ local_zones_create(void)
if(!zones)
return NULL;
rbtree_init(&zones->ztree, &local_zone_cmp);
lock_quick_init(&zones->lock);
lock_rw_init(&zones->lock);
lock_protect(&zones->lock, &zones->ztree, sizeof(zones->ztree));
/* also lock protects the rbnode's in struct local_zone */
return zones;
@ -78,7 +78,7 @@ local_zones_delete(struct local_zones* zones)
{
if(!zones)
return;
lock_quick_destroy(&zones->lock);
lock_rw_destroy(&zones->lock);
/* walk through zones and delete them all */
traverse_postorder(&zones->ztree, lzdel, NULL);
free(zones);
@ -174,16 +174,16 @@ lz_enter_zone_dname(struct local_zones* zones, uint8_t* nm, size_t len,
}
/* add to rbtree */
lock_quick_lock(&zones->lock);
lock_rw_wrlock(&zones->lock);
lock_rw_wrlock(&z->lock);
if(!rbtree_insert(&zones->ztree, &z->node)) {
log_warn("duplicate local-zone");
lock_rw_unlock(&z->lock);
local_zone_delete(z);
lock_quick_unlock(&zones->lock);
lock_rw_unlock(&zones->lock);
return NULL;
}
lock_quick_unlock(&zones->lock);
lock_rw_unlock(&zones->lock);
return z;
}
@ -490,14 +490,14 @@ lz_enter_rr_str(struct local_zones* zones, const char* rr)
return 0;
}
labs = dname_count_size_labels(rr_name, &len);
lock_quick_lock(&zones->lock);
lock_rw_rdlock(&zones->lock);
z = local_zones_lookup(zones, rr_name, len, labs, rr_class);
if(!z) {
lock_quick_unlock(&zones->lock);
lock_rw_unlock(&zones->lock);
fatal_exit("internal error: no zone for rr %s", rr);
}
lock_rw_wrlock(&z->lock);
lock_quick_unlock(&zones->lock);
lock_rw_unlock(&zones->lock);
free(rr_name);
r = lz_enter_rr_into_zone(z, rr);
lock_rw_unlock(&z->lock);
@ -530,13 +530,13 @@ lz_exists(struct local_zones* zones, const char* name)
log_err("bad name %s", name);
return 0;
}
lock_quick_lock(&zones->lock);
lock_rw_rdlock(&zones->lock);
if(rbtree_search(&zones->ztree, &z.node)) {
lock_quick_unlock(&zones->lock);
lock_rw_unlock(&zones->lock);
free(z.name);
return 1;
}
lock_quick_unlock(&zones->lock);
lock_rw_unlock(&zones->lock);
free(z.name);
return 0;
}
@ -693,7 +693,7 @@ init_parents(struct local_zones* zones)
{
struct local_zone* node, *prev = NULL, *p;
int m;
lock_quick_lock(&zones->lock);
lock_rw_wrlock(&zones->lock);
RBTREE_FOR(node, struct local_zone*, &zones->ztree) {
lock_rw_wrlock(&node->lock);
node->parent = NULL;
@ -718,7 +718,7 @@ init_parents(struct local_zones* zones)
prev = node;
lock_rw_unlock(&node->lock);
}
lock_quick_unlock(&zones->lock);
lock_rw_unlock(&zones->lock);
}
/** enter implicit transparent zone for local-data: without local-zone: */
@ -748,7 +748,7 @@ lz_setup_implicit(struct local_zones* zones, struct config_file* cfg)
return 0;
}
labs = dname_count_size_labels(rr_name, &len);
lock_quick_lock(&zones->lock);
lock_rw_rdlock(&zones->lock);
if(!local_zones_lookup(zones, rr_name, len, labs, rr_class)) {
if(!have_name) {
dclass = rr_class;
@ -763,7 +763,7 @@ lz_setup_implicit(struct local_zones* zones, struct config_file* cfg)
/* process other classes later */
free(rr_name);
have_other_classes = 1;
lock_quick_unlock(&zones->lock);
lock_rw_unlock(&zones->lock);
continue;
}
/* find smallest shared topdomain */
@ -774,7 +774,7 @@ lz_setup_implicit(struct local_zones* zones, struct config_file* cfg)
match = m;
}
} else free(rr_name);
lock_quick_unlock(&zones->lock);
lock_rw_unlock(&zones->lock);
}
if(have_name) {
uint8_t* n2;
@ -919,7 +919,7 @@ local_zone_out(struct local_zone* z)
void local_zones_print(struct local_zones* zones)
{
struct local_zone* z;
lock_quick_lock(&zones->lock);
lock_rw_rdlock(&zones->lock);
log_info("number of auth zones %u", (unsigned)zones->ztree.count);
RBTREE_FOR(z, struct local_zone*, &zones->ztree) {
lock_rw_rdlock(&z->lock);
@ -956,7 +956,7 @@ void local_zones_print(struct local_zones* zones)
local_zone_out(z);
lock_rw_unlock(&z->lock);
}
lock_quick_unlock(&zones->lock);
lock_rw_unlock(&zones->lock);
}
/** encode answer consisting of 1 rrset */
@ -1106,15 +1106,15 @@ local_zones_answer(struct local_zones* zones, struct query_info* qinfo,
struct local_data* ld;
struct local_zone* z;
int r;
lock_quick_lock(&zones->lock);
lock_rw_rdlock(&zones->lock);
z = local_zones_lookup(zones, qinfo->qname,
qinfo->qname_len, labs, qinfo->qclass);
if(!z) {
lock_quick_unlock(&zones->lock);
lock_rw_unlock(&zones->lock);
return 0;
}
lock_rw_rdlock(&z->lock);
lock_quick_unlock(&zones->lock);
lock_rw_unlock(&zones->lock);
if(local_data_answer(z, qinfo, edns, buf, temp, labs, &ld)) {
lock_rw_unlock(&z->lock);
@ -1238,20 +1238,22 @@ local_zones_add_RR(struct local_zones* zones, const char* rr)
return 0;
}
labs = dname_count_size_labels(rr_name, &len);
lock_quick_lock(&zones->lock);
/* could first try readlock then get writelock if zone does not exist,
* but we do not add enough RRs (from multiple threads) to optimize */
lock_rw_wrlock(&zones->lock);
z = local_zones_lookup(zones, rr_name, len, labs, rr_class);
if(!z) {
z = local_zones_add_zone(zones, rr_name, len, labs, rr_class,
local_zone_transparent);
if(!z) {
lock_quick_unlock(&zones->lock);
lock_rw_unlock(&zones->lock);
return 0;
}
} else {
free(rr_name);
}
lock_rw_wrlock(&z->lock);
lock_quick_unlock(&zones->lock);
lock_rw_unlock(&zones->lock);
r = lz_enter_rr_into_zone(z, rr);
lock_rw_unlock(&z->lock);
return r;
@ -1297,15 +1299,15 @@ void local_zones_del_data(struct local_zones* zones,
/* find zone */
struct local_zone* z;
struct local_data* d;
lock_quick_lock(&zones->lock);
lock_rw_rdlock(&zones->lock);
z = local_zones_lookup(zones, name, len, labs, dclass);
if(!z) {
/* no such zone, we're done */
lock_quick_unlock(&zones->lock);
lock_rw_unlock(&zones->lock);
return;
}
lock_rw_wrlock(&z->lock);
lock_quick_unlock(&zones->lock);
lock_rw_unlock(&zones->lock);
/* find the domain */
d = lz_find_node(z, name, len, labs);

View file

@ -78,7 +78,7 @@ enum localzone_type {
*/
struct local_zones {
/** lock on the localzone tree */
lock_quick_t lock;
lock_rw_t lock;
/** rbtree of struct local_zone */
rbtree_t ztree;
};