Skip to content
This repository

speed up net write if socket buffer large enough #715

Closed
wants to merge 1 commit into from

3 participants

darcy Saúl Ibarra Corretgé Fedor Indutny
darcy

add uv_try_write() to libuv, try to write as many bytes as possible
into socket buffer for nonblocking socket, if all data is written
successfully, async uv write can be avoid, thereby saving the
consumption of uv context and queue operations.

I've opened an issue in node, where explained the reason in detail:
joyent/node#4699

And the corresponding patch for node:
freedaxin/node@d0718d0

darcy freedaxin speed up net write if socket buffer large enough
add uv_try_write() to libuv, try to write as many bytes as possible
into socket buffer for nonblocking socket, if all data is written
successfully, async uv write can be avoid, thereby saving the
consumption of uv context and queue operations.
91d0d00
Saúl Ibarra Corretgé
Collaborator

This looks similar to what you were tying recently @indutny, maybe we can close this since it wasn't so helpful after all?

Fedor Indutny
Collaborator

Well, it won't work at windows, so I decided that it isn't worth having it. Anyway, @freedaxin I wonder how much improvement did it gave to you?

darcy

@indutny, I got a improvement about 30% in my project. Maybe the patch is not perfect, but the approach is right. I wonder what's your "tying recently"?

Fedor Indutny
Collaborator

#1028 , but it doesn't and won't work on windows :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Feb 21, 2013
darcy freedaxin speed up net write if socket buffer large enough
add uv_try_write() to libuv, try to write as many bytes as possible
into socket buffer for nonblocking socket, if all data is written
successfully, async uv write can be avoid, thereby saving the
consumption of uv context and queue operations.
91d0d00
This page is out of date. Refresh to see the latest.

Showing 3 changed files with 64 additions and 1 deletion. Show diff stats Hide diff stats

  1. +9 0 include/uv.h
  2. +25 0 src/unix/stream.c
  3. +30 1 src/win/stream.c
9 include/uv.h
@@ -594,6 +594,15 @@ UV_EXTERN int uv_write(uv_write_t* req, uv_stream_t* handle,
594 594 UV_EXTERN int uv_write2(uv_write_t* req, uv_stream_t* handle, uv_buf_t bufs[],
595 595 int bufcnt, uv_stream_t* send_handle, uv_write_cb cb);
596 596
  597 +/*
  598 + * try to write as many data as possible into system buffer for nonblocking io,
  599 + * if all data is written successfully, async uv wirte can be avoid.
  600 + * On success, returns the number of bytes sent.
  601 + * On error, retruns 0 if it needs retry,
  602 + * otherwise returns -1, and uv__set_sys_error() is called.
  603 + */
  604 +UV_EXTERN ssize_t uv_try_write(uv_stream_t* handle, const void* buf, size_t count);
  605 +
597 606 /* uv_write_t is a subclass of uv_req_t */
598 607 struct uv_write_s {
599 608 UV_REQ_FIELDS
25 src/unix/stream.c
@@ -1261,6 +1261,31 @@ int uv_write(uv_write_t* req, uv_stream_t* stream, uv_buf_t bufs[], int bufcnt,
1261 1261 }
1262 1262
1263 1263
  1264 +ssize_t uv_try_write(uv_stream_t* stream, const void* buf, size_t count) {
  1265 + ssize_t n;
  1266 + if (stream->type != UV_TCP) {
  1267 + /* only try write for tcp */
  1268 + return 0;
  1269 + }
  1270 +
  1271 + if(stream->write_queue_size > 0 || stream->connect_req) {
  1272 + /* do not write if there is data waiting in queue, or the socket is connecting */
  1273 + return 0;
  1274 + }
  1275 +
  1276 + n = write(uv__stream_fd(stream), buf, count);
  1277 +
  1278 + if (n < 0) {
  1279 + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
  1280 + return 0;
  1281 + }
  1282 + uv__set_sys_error(stream->loop, errno);
  1283 + return -1;
  1284 + }
  1285 + return n;
  1286 +}
  1287 +
  1288 +
1264 1289 static int uv__read_start_common(uv_stream_t* stream,
1265 1290 uv_alloc_cb alloc_cb,
1266 1291 uv_read_cb read_cb,
31 src/win/stream.c
@@ -159,10 +159,39 @@ int uv_write2(uv_write_t* req, uv_stream_t* handle, uv_buf_t bufs[], int bufcnt,
159 159 }
160 160
161 161
  162 +ssize_t uv_try_write(uv_stream_t* handle, const void* buf, size_t count) {
  163 + ssize_t n;
  164 + if (handle->type != UV_TCP) {
  165 + // only try write for tcp
  166 + return 0;
  167 + }
  168 + if (!(handle->flags & UV_HANDLE_WRITABLE)) {
  169 + uv__set_artificial_error(handle->loop, UV_EPIPE);
  170 + return -1;
  171 + }
  172 + if(handle->write_queue_size > 0) {
  173 + /* do not write if there is data waiting in queue */
  174 + return 0;
  175 + }
  176 +
  177 + n = send(((uv_tcp_t*) handle)->socket, buf, count, 0);
  178 +
  179 + if (n == SOCKET_ERROR) {
  180 + int last_err = WSAGetLastError();
  181 + if (last_err == WSAEWOULDBLOCK || last_err == WSAEINTR) {
  182 + return 0;
  183 + }
  184 + uv__set_sys_error(handle->loop, last_err);
  185 + return -1;
  186 + }
  187 + return n;
  188 +}
  189 +
  190 +
162 191 int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) {
163 192 uv_loop_t* loop = handle->loop;
164 193
165   - if (!(handle->flags & UV_HANDLE_WRITABLE)) {
  194 + if (!(handle->flags & UV_HANDLE_WRITABLE)) {
166 195 uv__set_artificial_error(loop, UV_EPIPE);
167 196 return -1;
168 197 }

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.