From: Lukáš Ondráček Date: Thu, 5 Dec 2024 18:50:57 +0000 (+0100) Subject: daemon/defer: improve time measuring X-Git-Tag: v6.0.10~6^2~21 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7cfa0103a9646734ab171e61a17462756f0ee15e;p=thirdparty%2Fknot-resolver.git daemon/defer: improve time measuring --- diff --git a/daemon/defer.c b/daemon/defer.c index df2566bed..aa29d2f1c 100644 --- a/daemon/defer.c +++ b/daemon/defer.c @@ -552,9 +552,11 @@ static enum protolayer_event_cb_result pl_defer_event_unwrap( // disable accounting only for events that cannot occur during incoming data processing phase_accounting = false; } - if (!defer || session->outgoing) + if (!defer || !session->stream || session->outgoing) return PROTOLAYER_EVENT_PROPAGATE; + defer_sample_addr((const union kr_sockaddr *)session->comm_storage.src_addr, session->stream); + struct pl_defer_sess_data *sdata = sess_data; if ((event == PROTOLAYER_EVENT_EOF) && (queue_len(sdata->queue) > 0)) { // defer EOF event if unprocessed data remain, baton is dropped if any diff --git a/daemon/defer.h b/daemon/defer.h index 5a26faa67..b24ee70ec 100644 --- a/daemon/defer.h +++ b/daemon/defer.h @@ -102,6 +102,11 @@ static inline void defer_sample_stop_stamp(uint64_t stamp) defer_charge(elapsed, &defer_sample_state.addr, defer_sample_state.stream); } +static inline bool defer_sample_is_accounting(void) +{ + return defer_sample_state.is_accounting; +} + /// Start accounting work; optionally save state of current accounting. /// Current state can be saved only after having an address assigned. static inline void defer_sample_start(defer_sample_state_t *prev_state_out) { diff --git a/daemon/session2.c b/daemon/session2.c index c1c0d7cee..faca57bfe 100644 --- a/daemon/session2.c +++ b/daemon/session2.c @@ -980,10 +980,8 @@ uv_handle_t *session2_get_handle(struct session2 *s) static void session2_on_timeout(uv_timer_t *timer) { - defer_sample_start(NULL); struct session2 *s = timer->data; session2_event(s, s->timer_event, NULL); - defer_sample_stop(NULL, false); } int session2_timer_start(struct session2 *s, enum protolayer_event_type event, uint64_t timeout, uint64_t repeat) @@ -1347,7 +1345,19 @@ static void session2_event_unwrap(struct session2 *s, ssize_t start_ix, enum pro void session2_event(struct session2 *s, enum protolayer_event_type event, void *baton) { + /* Events may be sent from inside or outside of already measured code. + * From inside: close by us, statistics, ... + * From outside: timeout, EOF, close by external reasons, ... */ + bool defer_accounting_here = false; + if (!defer_sample_is_accounting() && s->stream && !s->outgoing) { + defer_sample_start(NULL); + defer_accounting_here = true; + } + session2_event_unwrap(s, 0, event, baton); + + if (defer_accounting_here) + defer_sample_stop(NULL, false); } void session2_event_after(struct session2 *s, enum protolayer_type protocol, diff --git a/daemon/worker.c b/daemon/worker.c index 55c916904..ece3fd953 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -703,10 +703,18 @@ static struct kr_query *task_get_last_pending_query(struct qr_task *task) static int send_waiting(struct session2 *session) { + if (session2_waitinglist_is_empty(session)) + return 0; + + defer_sample_state_t defer_prev_sample_state; + defer_sample_start(&defer_prev_sample_state); int ret = 0; - while (!session2_waitinglist_is_empty(session)) { + do { struct qr_task *t = session2_waitinglist_get(session); + if (t->ctx->source.session) + defer_sample_addr(&t->ctx->source.addr, t->ctx->source.session->stream); ret = qr_task_send(t, session, NULL, NULL); + defer_sample_restart(); if (ret != 0) { struct sockaddr *peer = session2_get_peer(session); session2_waitinglist_finalize(session, KR_STATE_FAIL); @@ -716,7 +724,9 @@ static int send_waiting(struct session2 *session) break; } session2_waitinglist_pop(session, true); - } + } while (!session2_waitinglist_is_empty(session)); + defer_sample_stop(&defer_prev_sample_state, true); + return ret; } @@ -1878,13 +1888,19 @@ static enum protolayer_event_cb_result pl_dns_stream_resolution_timeout( } else { /* Normally it should not happen, * but better to check if there anything in this list. */ - while (!session2_waitinglist_is_empty(s)) { - struct qr_task *t = session2_waitinglist_pop(s, false); - worker_task_finalize(t, KR_STATE_FAIL); - worker_task_unref(t); - the_worker->stats.timeout += 1; - if (s->closing) - return PROTOLAYER_EVENT_PROPAGATE; + if (!session2_waitinglist_is_empty(s)) { + defer_sample_state_t defer_prev_sample_state; + defer_sample_start(&defer_prev_sample_state); + do { + struct qr_task *t = session2_waitinglist_pop(s, false); + worker_task_finalize(t, KR_STATE_FAIL); + worker_task_unref(t); + the_worker->stats.timeout += 1; + if (s->closing) + return PROTOLAYER_EVENT_PROPAGATE; + defer_sample_restart(); + } while (!session2_waitinglist_is_empty(s)); + defer_sample_stop(&defer_prev_sample_state, true); } uint64_t idle_in_timeout = the_network->tcp.in_idle_timeout; uint64_t idle_time = kr_now() - s->last_activity; @@ -1997,6 +2013,13 @@ static enum protolayer_event_cb_result pl_dns_stream_disconnected( stream->connected = false; + if (session2_is_empty(session)) + return PROTOLAYER_EVENT_PROPAGATE; + + defer_sample_state_t defer_prev_sample_state; + if (session->outgoing) + defer_sample_start(&defer_prev_sample_state); + while (!session2_waitinglist_is_empty(session)) { struct qr_task *task = session2_waitinglist_pop(session, false); kr_assert(task->refs > 1); @@ -2013,6 +2036,7 @@ static enum protolayer_event_cb_result pl_dns_stream_disconnected( qry->flags.TCP = false; } qr_task_step(task, NULL, NULL); + defer_sample_restart(); } else { kr_assert(task->ctx->source.session == session); task->ctx->source.session = NULL; @@ -2029,6 +2053,7 @@ static enum protolayer_event_cb_result pl_dns_stream_disconnected( qry->flags.TCP = false; } qr_task_step(task, NULL, NULL); + defer_sample_restart(); } else { kr_assert(task->ctx->source.session == session); task->ctx->source.session = NULL; @@ -2036,6 +2061,9 @@ static enum protolayer_event_cb_result pl_dns_stream_disconnected( worker_task_unref(task); } + if (session->outgoing) + defer_sample_stop(&defer_prev_sample_state, true); + return PROTOLAYER_EVENT_PROPAGATE; }