Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnna Henningsen <anna@addaleax.net>2019-10-03 00:26:51 +0300
committerRich Trott <rtrott@gmail.com>2019-10-06 03:48:10 +0300
commitafdc3d0d187e4e3a336937df17a4c90092405e2a (patch)
treef16e7b4920a24d3ed7e711380450bd8b302ee40b /src/udp_wrap.cc
parent28c3a9dd723e124a0e38588826c737eee7bfded5 (diff)
dgram: use `uv_udp_try_send()`
This improves dgram performance by avoiding unnecessary async operations. One issue with this commit is that it seems hard to actually create conditions under which the fallback path to the async case is actually taken, for all supported OS, so an internal CLI option is used for testing that path. Another caveat is that the lack of an async operation means that there are slight timing differences (essentially `nextTick()` rather than `setImmediate()` for the send callback). PR-URL: https://github.com/nodejs/node/pull/29832 Reviewed-By: David Carlier <devnexen@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'src/udp_wrap.cc')
-rw-r--r--src/udp_wrap.cc44
1 files changed, 33 insertions, 11 deletions
diff --git a/src/udp_wrap.cc b/src/udp_wrap.cc
index 3c66db2155a..64c4c8b304f 100644
--- a/src/udp_wrap.cc
+++ b/src/udp_wrap.cc
@@ -429,11 +429,6 @@ void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) {
size_t count = args[2].As<Uint32>()->Value();
const bool have_callback = sendto ? args[5]->IsTrue() : args[3]->IsTrue();
- SendWrap* req_wrap;
- {
- AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(wrap);
- req_wrap = new SendWrap(env, req_wrap_obj, have_callback);
- }
size_t msg_size = 0;
MaybeStackBuffer<uv_buf_t, 16> bufs(count);
@@ -448,8 +443,6 @@ void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) {
msg_size += length;
}
- req_wrap->msg_size = msg_size;
-
int err = 0;
struct sockaddr_storage addr_storage;
sockaddr* addr = nullptr;
@@ -462,18 +455,47 @@ void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) {
}
}
+ uv_buf_t* bufs_ptr = *bufs;
+ if (err == 0 && !UNLIKELY(env->options()->test_udp_no_try_send)) {
+ err = uv_udp_try_send(&wrap->handle_, bufs_ptr, count, addr);
+ if (err == UV_ENOSYS || err == UV_EAGAIN) {
+ err = 0;
+ } else if (err >= 0) {
+ size_t sent = err;
+ while (count > 0 && bufs_ptr->len <= sent) {
+ sent -= bufs_ptr->len;
+ bufs_ptr++;
+ count--;
+ }
+ if (count > 0) {
+ CHECK_LT(sent, bufs_ptr->len);
+ bufs_ptr->base += sent;
+ bufs_ptr->len -= sent;
+ } else {
+ CHECK_EQ(static_cast<size_t>(err), msg_size);
+ // + 1 so that the JS side can distinguish 0-length async sends from
+ // 0-length sync sends.
+ args.GetReturnValue().Set(static_cast<uint32_t>(msg_size) + 1);
+ return;
+ }
+ }
+ }
+
if (err == 0) {
+ AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(wrap);
+ SendWrap* req_wrap = new SendWrap(env, req_wrap_obj, have_callback);
+ req_wrap->msg_size = msg_size;
+
err = req_wrap->Dispatch(uv_udp_send,
&wrap->handle_,
- *bufs,
+ bufs_ptr,
count,
addr,
OnSend);
+ if (err)
+ delete req_wrap;
}
- if (err)
- delete req_wrap;
-
args.GetReturnValue().Set(err);
}