aboutsummaryrefslogtreecommitdiff
path: root/ares/ares_query.c
diff options
context:
space:
mode:
authorSteinar H. Gunderson <sesse@google.com>2007-09-29 18:18:47 +0000
committerSteinar H. Gunderson <sesse@google.com>2007-09-29 18:18:47 +0000
commit23f5d145ec69e2a8b62e75cc49b591fef04ca48d (patch)
tree3bbbeb0269bb896342bc24b839d7b5ac966bf6f7 /ares/ares_query.c
parentb01ab65225dec292919f8123ef2557d0a94e4569 (diff)
Previously, processing a large batch of timeouts was O(n^2) in the number of
outstanding queries, and processing a DNS response packet was O(n) in the number of outstanding queries. To speed things up in Google, we added a few circular, doubly-linked lists of queries that are hash-bucketed based on the attributes we care about, so most important operations are now O(1). It might be that the number of buckets are higher than most people would need, but on a quick calculation it should only be 100kB or so even on a 64-bit system, so I've let it stay as-is.
Diffstat (limited to 'ares/ares_query.c')
-rw-r--r--ares/ares_query.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/ares/ares_query.c b/ares/ares_query.c
index c5fc12449..c7c31edd9 100644
--- a/ares/ares_query.c
+++ b/ares/ares_query.c
@@ -68,15 +68,19 @@ void ares__rc4(rc4_key* key, unsigned char *buffer_ptr, int buffer_len)
static struct query* find_query_by_id(ares_channel channel, int id)
{
unsigned short qid;
- struct query* q;
+ struct list_node* list_head;
+ struct list_node* list_node;
DNS_HEADER_SET_QID(((unsigned char*)&qid), id);
/* Find the query corresponding to this packet. */
- for (q = channel->queries; q; q = q->next)
- {
- if (q->qid == qid)
+ list_head = &(channel->queries_by_qid[qid % ARES_QID_TABLE_SIZE]);
+ for (list_node = list_head->next; list_node != list_head;
+ list_node = list_node->next)
+ {
+ struct query *q = list_node->data;
+ if (q->qid == qid)
return q;
- }
+ }
return NULL;
}