mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-03 16:15:27 +00:00
- isc_task_create_bound - create a task bound to specific task queue
If we know that we'll have a task pool doing specific thing it's better to use this knowledge and bind tasks to task queues, this behaves better than randomly choosing the task queue. - use bound resolver tasks - we have a pool of tasks doing resolutions, we can spread the load evenly using isc_task_create_bound - quantum set universally to 25
This commit is contained in:
committed by
Witold Krecicki
parent
54b4e4e61c
commit
d5793ecca2
2
CHANGES
2
CHANGES
@@ -1,3 +1,5 @@
|
||||
5100. [func] Pin resolver tasks to specific task queues. [GL !1117]
|
||||
|
||||
5099. [func] Failed mutex and conditional creations are always
|
||||
fatal. [GL #674]
|
||||
|
||||
|
@@ -458,7 +458,7 @@ dns_client_createx(isc_mem_t *mctx, isc_appctx_t *actx,
|
||||
client->timermgr = timermgr;
|
||||
|
||||
client->task = NULL;
|
||||
result = isc_task_create(client->taskmgr, 50, &client->task);
|
||||
result = isc_task_create(client->taskmgr, 0, &client->task);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
|
@@ -2918,7 +2918,7 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
|
||||
}
|
||||
for (i = 0; i < disp->ntasks; i++) {
|
||||
disp->task[i] = NULL;
|
||||
result = isc_task_create(taskmgr, 50, &disp->task[i]);
|
||||
result = isc_task_create(taskmgr, 0, &disp->task[i]);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
while (--i >= 0) {
|
||||
isc_task_shutdown(disp->task[i]);
|
||||
|
@@ -4382,8 +4382,8 @@ fctx_shutdown(fetchctx_t *fctx) {
|
||||
*/
|
||||
if (fctx->state != fetchstate_init) {
|
||||
cevent = &fctx->control_event;
|
||||
isc_task_send(fctx->res->buckets[fctx->bucketnum].task,
|
||||
&cevent);
|
||||
isc_task_sendto(fctx->res->buckets[fctx->bucketnum].task,
|
||||
&cevent, fctx->bucketnum);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9924,7 +9924,12 @@ dns_resolver_create(dns_view_t *view,
|
||||
isc_mutex_init(&res->buckets[i].lock);
|
||||
|
||||
res->buckets[i].task = NULL;
|
||||
result = isc_task_create(taskmgr, 0, &res->buckets[i].task);
|
||||
/*
|
||||
* Since we have a pool of tasks we bind them to task queues
|
||||
* to spread the load evenly
|
||||
*/
|
||||
result = isc_task_create_bound(taskmgr, 0,
|
||||
&res->buckets[i].task, i);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_mutex_destroy(&res->buckets[i].lock);
|
||||
goto cleanup_buckets;
|
||||
|
@@ -136,6 +136,10 @@ struct isc_task {
|
||||
isc_result_t
|
||||
isc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
|
||||
isc_task_t **taskp);
|
||||
|
||||
isc_result_t
|
||||
isc_task_create_bound(isc_taskmgr_t *manager, unsigned int quantum,
|
||||
isc_task_t **taskp, int threadid);
|
||||
/*%<
|
||||
* Create a task.
|
||||
*
|
||||
|
@@ -49,6 +49,10 @@
|
||||
* state it will stay on the runner it's currently on, if a task is in idle
|
||||
* state it can be woken up on a specific runner with isc_task_sendto - that
|
||||
* helps with data locality on CPU.
|
||||
*
|
||||
* To make load even some tasks (from task pools) are bound to specific
|
||||
* queues using isc_task_create_bound. This way load balancing between
|
||||
* CPUs/queues happens on the higher layer.
|
||||
*/
|
||||
|
||||
#ifdef ISC_TASK_TRACE
|
||||
@@ -104,6 +108,7 @@ struct isc__task {
|
||||
char name[16];
|
||||
void * tag;
|
||||
unsigned int threadid;
|
||||
bool bound;
|
||||
/* Locked by task manager lock. */
|
||||
LINK(isc__task_t) link;
|
||||
LINK(isc__task_t) ready_link;
|
||||
@@ -171,8 +176,7 @@ void
|
||||
isc__taskmgr_resume(isc_taskmgr_t *manager0);
|
||||
|
||||
|
||||
#define DEFAULT_TASKMGR_QUANTUM 10
|
||||
#define DEFAULT_DEFAULT_QUANTUM 5
|
||||
#define DEFAULT_DEFAULT_QUANTUM 25
|
||||
#define FINISHED(m) ((m)->exiting && EMPTY((m)->tasks))
|
||||
|
||||
/*%
|
||||
@@ -244,6 +248,13 @@ task_finished(isc__task_t *task) {
|
||||
isc_result_t
|
||||
isc_task_create(isc_taskmgr_t *manager0, unsigned int quantum,
|
||||
isc_task_t **taskp)
|
||||
{
|
||||
return (isc_task_create_bound(manager0, quantum, taskp, -1));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_task_create_bound(isc_taskmgr_t *manager0, unsigned int quantum,
|
||||
isc_task_t **taskp, int threadid)
|
||||
{
|
||||
isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
|
||||
isc__task_t *task;
|
||||
@@ -257,17 +268,31 @@ isc_task_create(isc_taskmgr_t *manager0, unsigned int quantum,
|
||||
return (ISC_R_NOMEMORY);
|
||||
XTRACE("isc_task_create");
|
||||
task->manager = manager;
|
||||
task->threadid = atomic_fetch_add_explicit(&manager->curq, 1,
|
||||
memory_order_relaxed)
|
||||
% manager->workers;
|
||||
isc_mutex_init(&task->lock);
|
||||
|
||||
if (threadid == -1) {
|
||||
/*
|
||||
* Task is not pinned to a queue, it's threadid will be
|
||||
* choosen when first task will be sent to it - either
|
||||
* randomly or specified by isc_task_sendto.
|
||||
*/
|
||||
task->bound = false;
|
||||
task->threadid = 0;
|
||||
} else {
|
||||
/*
|
||||
* Task is pinned to a queue, it'll always be run
|
||||
* by a specific thread.
|
||||
*/
|
||||
task->bound = true;
|
||||
task->threadid = threadid % manager->workers;
|
||||
}
|
||||
|
||||
isc_mutex_init(&task->lock);
|
||||
task->state = task_state_idle;
|
||||
task->references = 1;
|
||||
INIT_LIST(task->events);
|
||||
INIT_LIST(task->on_shutdown);
|
||||
task->nevents = 0;
|
||||
task->quantum = quantum;
|
||||
task->quantum = (quantum > 0) ? quantum : manager->default_quantum;
|
||||
task->flags = 0;
|
||||
task->now = 0;
|
||||
isc_time_settoepoch(&task->tnow);
|
||||
@@ -280,11 +305,10 @@ isc_task_create(isc_taskmgr_t *manager0, unsigned int quantum,
|
||||
exiting = false;
|
||||
LOCK(&manager->lock);
|
||||
if (!manager->exiting) {
|
||||
if (task->quantum == 0)
|
||||
task->quantum = manager->default_quantum;
|
||||
APPEND(manager->tasks, task, link);
|
||||
} else
|
||||
} else {
|
||||
exiting = true;
|
||||
}
|
||||
UNLOCK(&manager->lock);
|
||||
|
||||
if (exiting) {
|
||||
@@ -490,7 +514,10 @@ isc_task_sendto(isc_task_t *task0, isc_event_t **eventp, int c) {
|
||||
REQUIRE(VALID_TASK(task));
|
||||
XTRACE("isc_task_send");
|
||||
|
||||
if (c < 0) {
|
||||
/* If task is bound ignore provided cpu. */
|
||||
if (task->bound) {
|
||||
c = task->threadid;
|
||||
} else if (c < 0) {
|
||||
c = atomic_fetch_add_explicit(&task->manager->curq, 1,
|
||||
memory_order_relaxed);
|
||||
}
|
||||
@@ -540,7 +567,9 @@ isc_task_sendtoanddetach(isc_task_t **taskp, isc_event_t **eventp, int c) {
|
||||
REQUIRE(VALID_TASK(task));
|
||||
XTRACE("isc_task_sendanddetach");
|
||||
|
||||
if (c < 0) {
|
||||
if (task->bound) {
|
||||
c = task->threadid;
|
||||
} else if (c < 0) {
|
||||
c = atomic_fetch_add_explicit(&task->manager->curq, 1,
|
||||
memory_order_relaxed);
|
||||
}
|
||||
|
@@ -566,6 +566,7 @@ isc_syslog_facilityfromstring
|
||||
isc_task_attach
|
||||
isc_task_beginexclusive
|
||||
isc_task_create
|
||||
isc_task_create_bound
|
||||
isc_task_destroy
|
||||
isc_task_detach
|
||||
isc_task_endexclusive
|
||||
|
@@ -2964,7 +2964,7 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) {
|
||||
ns_server_attach(manager->sctx, &client->sctx);
|
||||
|
||||
client->task = NULL;
|
||||
result = isc_task_create(manager->taskmgr, 50, &client->task);
|
||||
result = isc_task_create(manager->taskmgr, 0, &client->task);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_client;
|
||||
isc_task_setname(client->task, "client", client);
|
||||
|
Reference in New Issue
Block a user