]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Avoid netievent allocations when the callbacks can be called directly
authorOndřej Surý <ondrej@sury.org>
Wed, 2 Dec 2020 07:54:51 +0000 (08:54 +0100)
committerOndřej Surý <ondrej@sury.org>
Wed, 9 Dec 2020 09:46:16 +0000 (10:46 +0100)
After turning the users callbacks to be asynchronous, there was a
visible performance drop.  This commit prevents the unnecessary
allocations while keeping the code paths same for both asynchronous and
synchronous calls.

The same change was done to the isc__nm_udp_{read,send} as those two
functions are in the hot path.

(cherry picked from commit d6d2fbe0e9ad3eb85bb823fc534330bde7d2df6a)

lib/isc/netmgr/netmgr.c
lib/isc/netmgr/udp.c

index d052b7f9bb003407913dd2daceb0850cddda16da..8f5c78d01b7de3dcf705d201ccd8b843fe8a82a2 100644 (file)
@@ -1784,13 +1784,15 @@ isc__nm_connectcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
        REQUIRE(VALID_UVREQ(uvreq));
        REQUIRE(VALID_NMHANDLE(uvreq->handle));
 
-       isc__netievent_connectcb_t *ievent = isc__nm_get_netievent_connectcb(
-               sock->mgr, sock, uvreq, eresult);
-
        if (eresult == ISC_R_SUCCESS) {
-               isc__nm_maybe_enqueue_ievent(&sock->mgr->workers[sock->tid],
-                                            (isc__netievent_t *)ievent);
+               isc__netievent_connectcb_t ievent = { .sock = sock,
+                                                     .req = uvreq,
+                                                     .result = eresult };
+               isc__nm_async_connectcb(NULL, (isc__netievent_t *)&ievent);
        } else {
+               isc__netievent_connectcb_t *ievent =
+                       isc__nm_get_netievent_connectcb(sock->mgr, sock, uvreq,
+                                                       eresult);
                isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
                                       (isc__netievent_t *)ievent);
        }
@@ -1823,14 +1825,15 @@ isc__nm_readcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
        REQUIRE(VALID_UVREQ(uvreq));
        REQUIRE(VALID_NMHANDLE(uvreq->handle));
 
-       isc__netievent_readcb_t *ievent =
-               isc__nm_get_netievent_readcb(sock->mgr, sock, uvreq, eresult);
-
        if (eresult == ISC_R_SUCCESS) {
-               REQUIRE(sock->tid == isc_nm_tid());
-               isc__nm_maybe_enqueue_ievent(&sock->mgr->workers[sock->tid],
-                                            (isc__netievent_t *)ievent);
+               isc__netievent_readcb_t ievent = { .sock = sock,
+                                                  .req = uvreq,
+                                                  .result = eresult };
+
+               isc__nm_async_readcb(NULL, (isc__netievent_t *)&ievent);
        } else {
+               isc__netievent_readcb_t *ievent = isc__nm_get_netievent_readcb(
+                       sock->mgr, sock, uvreq, eresult);
                isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
                                       (isc__netievent_t *)ievent);
        }
@@ -1864,14 +1867,14 @@ isc__nm_sendcb(isc_nmsocket_t *sock, isc__nm_uvreq_t *uvreq,
        REQUIRE(VALID_UVREQ(uvreq));
        REQUIRE(VALID_NMHANDLE(uvreq->handle));
 
-       isc__netievent_sendcb_t *ievent =
-               isc__nm_get_netievent_sendcb(sock->mgr, sock, uvreq, eresult);
-
        if (eresult == ISC_R_SUCCESS) {
-               REQUIRE(sock->tid == isc_nm_tid());
-               isc__nm_maybe_enqueue_ievent(&sock->mgr->workers[sock->tid],
-                                            (isc__netievent_t *)ievent);
+               isc__netievent_sendcb_t ievent = { .sock = sock,
+                                                  .req = uvreq,
+                                                  .result = eresult };
+               isc__nm_async_sendcb(NULL, (isc__netievent_t *)&ievent);
        } else {
+               isc__netievent_sendcb_t *ievent = isc__nm_get_netievent_sendcb(
+                       sock->mgr, sock, uvreq, eresult);
                isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
                                       (isc__netievent_t *)ievent);
        }
index 22055c3382aa3db04f9ae8ecffa1e4dd06257514..726efd6f0f10b04884f694fa4b4f10be6933f5a0 100644 (file)
@@ -454,7 +454,6 @@ isc__nm_udp_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
        isc_nmsocket_t *sock = handle->sock;
        isc_nmsocket_t *psock = NULL, *rsock = sock;
        isc_sockaddr_t *peer = &handle->peer;
-       isc__netievent_udpsend_t *ievent = NULL;
        isc__nm_uvreq_t *uvreq = NULL;
        uint32_t maxudp = atomic_load(&sock->mgr->maxudp);
        int ntid;
@@ -512,23 +511,14 @@ isc__nm_udp_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
        }
 
        if (isc_nm_tid() == rsock->tid) {
-               /*
-                * If we're in the same thread as the socket we can send
-                * the data directly, but we still need to return errors
-                * via the callback for API consistency.
-                */
-               isc_result_t result = udp_send_direct(rsock, uvreq, peer);
-               if (result != ISC_R_SUCCESS) {
-                       isc__nm_incstats(rsock->mgr,
-                                        rsock->statsindex[STATID_SENDFAIL]);
-                       failed_send_cb(rsock, uvreq, result);
-               }
+               isc__netievent_udpsend_t ievent = { .sock = rsock,
+                                                   .req = uvreq,
+                                                   .peer = *peer };
+
+               isc__nm_async_udpsend(NULL, (isc__netievent_t *)&ievent);
        } else {
-               /*
-                * We need to create an event and pass it using async
-                * channel
-                */
-               ievent = isc__nm_get_netievent_udpsend(sock->mgr, rsock);
+               isc__netievent_udpsend_t *ievent =
+                       isc__nm_get_netievent_udpsend(sock->mgr, rsock);
                ievent->peer = *peer;
                ievent->req = uvreq;
 
@@ -551,7 +541,7 @@ isc__nm_async_udpsend(isc__networker_t *worker, isc__netievent_t *ev0) {
        REQUIRE(sock->tid == isc_nm_tid());
        UNUSED(worker);
 
-       if (!isc__nmsocket_active(ievent->sock)) {
+       if (inactive(sock)) {
                failed_send_cb(sock, uvreq, ISC_R_CANCELED);
                return;
        }
@@ -1000,7 +990,6 @@ isc__nm_udp_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) {
        REQUIRE(VALID_NMSOCK(handle->sock));
 
        isc_nmsocket_t *sock = handle->sock;
-       isc__netievent_udpread_t *ievent = NULL;
 
        REQUIRE(sock->type == isc_nm_udpsocket);
        REQUIRE(sock->statichandle == handle);
@@ -1011,14 +1000,14 @@ isc__nm_udp_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) {
        sock->recv_cbarg = cbarg;
        sock->recv_read = true;
 
-       ievent = isc__nm_get_netievent_udpread(sock->mgr, sock);
-
-       if (sock->reading) {
+       if (!sock->reading && sock->tid == isc_nm_tid()) {
+               isc__netievent_udpread_t ievent = { .sock = sock };
+               isc__nm_async_udpread(NULL, (isc__netievent_t *)&ievent);
+       } else {
+               isc__netievent_udpread_t *ievent =
+                       isc__nm_get_netievent_udpread(sock->mgr, sock);
                isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
                                       (isc__netievent_t *)ievent);
-       } else {
-               isc__nm_maybe_enqueue_ievent(&sock->mgr->workers[sock->tid],
-                                            (isc__netievent_t *)ievent);
        }
 }