windows: knob for tuning number of concurrent accept requests
This commit is contained in:
parent
bd82d02467
commit
78f4b120a1
@ -247,6 +247,7 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
|
||||
|
||||
#define uv_tcp_server_fields \
|
||||
uv_tcp_accept_t* accept_reqs; \
|
||||
unsigned int processed_accepts; \
|
||||
uv_tcp_accept_t* pending_accepts; \
|
||||
LPFN_ACCEPTEX func_acceptex;
|
||||
|
||||
|
||||
10
include/uv.h
10
include/uv.h
@ -481,6 +481,16 @@ UV_EXTERN int uv_tcp_nodelay(uv_tcp_t* handle, int enable);
|
||||
UV_EXTERN int uv_tcp_keepalive(uv_tcp_t* handle, int enable,
|
||||
unsigned int delay);
|
||||
|
||||
/*
|
||||
* This setting applies to Windows only.
|
||||
* Enable/disable simultaneous asynchronous accept requests that are
|
||||
* queued by the operating system when listening for new tcp connections.
|
||||
* This setting is used to tune a tcp server for the desired performance.
|
||||
* Having simultaneous accepts can significantly improve the rate of
|
||||
* accepting connections (which is why it is enabled by default).
|
||||
*/
|
||||
UV_EXTERN int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable);
|
||||
|
||||
UV_EXTERN int uv_tcp_bind(uv_tcp_t* handle, struct sockaddr_in);
|
||||
UV_EXTERN int uv_tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6);
|
||||
UV_EXTERN int uv_tcp_getsockname(uv_tcp_t* handle, struct sockaddr* name,
|
||||
|
||||
@ -319,3 +319,8 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_tcp_multiple_simultaneous_accepts(uv_tcp_t* handle, int enable) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -44,33 +44,35 @@ void uv_process_timers(uv_loop_t* loop);
|
||||
*/
|
||||
|
||||
/* Private uv_handle flags */
|
||||
#define UV_HANDLE_CLOSING 0x0000001
|
||||
#define UV_HANDLE_CLOSED 0x0000002
|
||||
#define UV_HANDLE_BOUND 0x0000004
|
||||
#define UV_HANDLE_LISTENING 0x0000008
|
||||
#define UV_HANDLE_CONNECTION 0x0000010
|
||||
#define UV_HANDLE_CONNECTED 0x0000020
|
||||
#define UV_HANDLE_READING 0x0000040
|
||||
#define UV_HANDLE_ACTIVE 0x0000040
|
||||
#define UV_HANDLE_EOF 0x0000080
|
||||
#define UV_HANDLE_SHUTTING 0x0000100
|
||||
#define UV_HANDLE_SHUT 0x0000200
|
||||
#define UV_HANDLE_ENDGAME_QUEUED 0x0000400
|
||||
#define UV_HANDLE_BIND_ERROR 0x0001000
|
||||
#define UV_HANDLE_IPV6 0x0002000
|
||||
#define UV_HANDLE_PIPESERVER 0x0004000
|
||||
#define UV_HANDLE_READ_PENDING 0x0008000
|
||||
#define UV_HANDLE_UV_ALLOCED 0x0010000
|
||||
#define UV_HANDLE_SYNC_BYPASS_IOCP 0x0020000
|
||||
#define UV_HANDLE_ZERO_READ 0x0040000
|
||||
#define UV_HANDLE_TTY_RAW 0x0080000
|
||||
#define UV_HANDLE_EMULATE_IOCP 0x0100000
|
||||
#define UV_HANDLE_NON_OVERLAPPED_PIPE 0x0200000
|
||||
#define UV_HANDLE_TTY_SAVED_POSITION 0x0400000
|
||||
#define UV_HANDLE_TTY_SAVED_ATTRIBUTES 0x0800000
|
||||
#define UV_HANDLE_SHARED_TCP_SERVER 0x1000000
|
||||
#define UV_HANDLE_TCP_NODELAY 0x2000000
|
||||
#define UV_HANDLE_TCP_KEEPALIVE 0x4000000
|
||||
#define UV_HANDLE_CLOSING 0x00000001
|
||||
#define UV_HANDLE_CLOSED 0x00000002
|
||||
#define UV_HANDLE_BOUND 0x00000004
|
||||
#define UV_HANDLE_LISTENING 0x00000008
|
||||
#define UV_HANDLE_CONNECTION 0x00000010
|
||||
#define UV_HANDLE_CONNECTED 0x00000020
|
||||
#define UV_HANDLE_READING 0x00000040
|
||||
#define UV_HANDLE_ACTIVE 0x00000040
|
||||
#define UV_HANDLE_EOF 0x00000080
|
||||
#define UV_HANDLE_SHUTTING 0x00000100
|
||||
#define UV_HANDLE_SHUT 0x00000200
|
||||
#define UV_HANDLE_ENDGAME_QUEUED 0x00000400
|
||||
#define UV_HANDLE_BIND_ERROR 0x00001000
|
||||
#define UV_HANDLE_IPV6 0x00002000
|
||||
#define UV_HANDLE_PIPESERVER 0x00004000
|
||||
#define UV_HANDLE_READ_PENDING 0x00008000
|
||||
#define UV_HANDLE_UV_ALLOCED 0x00010000
|
||||
#define UV_HANDLE_SYNC_BYPASS_IOCP 0x00020000
|
||||
#define UV_HANDLE_ZERO_READ 0x00040000
|
||||
#define UV_HANDLE_TTY_RAW 0x00080000
|
||||
#define UV_HANDLE_EMULATE_IOCP 0x00100000
|
||||
#define UV_HANDLE_NON_OVERLAPPED_PIPE 0x00200000
|
||||
#define UV_HANDLE_TTY_SAVED_POSITION 0x00400000
|
||||
#define UV_HANDLE_TTY_SAVED_ATTRIBUTES 0x00800000
|
||||
#define UV_HANDLE_SHARED_TCP_SERVER 0x01000000
|
||||
#define UV_HANDLE_TCP_NODELAY 0x02000000
|
||||
#define UV_HANDLE_TCP_KEEPALIVE 0x04000000
|
||||
#define UV_HANDLE_TCP_SINGLE_ACCEPT 0x08000000
|
||||
#define UV_HANDLE_TCP_ACCEPT_STATE_CHANGING 0x10000000
|
||||
|
||||
void uv_want_endgame(uv_loop_t* loop, uv_handle_t* handle);
|
||||
void uv_process_endgames(uv_loop_t* loop);
|
||||
|
||||
@ -152,6 +152,7 @@ int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) {
|
||||
handle->reqs_pending = 0;
|
||||
handle->func_acceptex = NULL;
|
||||
handle->func_connectex = NULL;
|
||||
handle->processed_accepts = 0;
|
||||
|
||||
loop->counters.tcp_init++;
|
||||
|
||||
@ -439,7 +440,7 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) {
|
||||
|
||||
int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
|
||||
uv_loop_t* loop = handle->loop;
|
||||
unsigned int i;
|
||||
unsigned int i, simultaneous_accepts;
|
||||
uv_tcp_accept_t* req;
|
||||
|
||||
assert(backlog > 0);
|
||||
@ -469,14 +470,17 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
|
||||
handle->flags |= UV_HANDLE_LISTENING;
|
||||
handle->connection_cb = cb;
|
||||
|
||||
simultaneous_accepts = handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT ? 1
|
||||
: uv_simultaneous_server_accepts;
|
||||
|
||||
if(!handle->accept_reqs) {
|
||||
handle->accept_reqs = (uv_tcp_accept_t*)
|
||||
malloc(uv_simultaneous_server_accepts * sizeof(uv_tcp_accept_t));
|
||||
malloc(simultaneous_accepts * sizeof(uv_tcp_accept_t));
|
||||
if (!handle->accept_reqs) {
|
||||
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
|
||||
}
|
||||
|
||||
for (i = 0; i < uv_simultaneous_server_accepts; i++) {
|
||||
for (i = 0; i < simultaneous_accepts; i++) {
|
||||
req = &handle->accept_reqs[i];
|
||||
uv_req_init(loop, (uv_req_t*)req);
|
||||
req->type = UV_ACCEPT;
|
||||
@ -533,7 +537,26 @@ int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) {
|
||||
req->accept_socket = INVALID_SOCKET;
|
||||
|
||||
if (!(server->flags & UV_HANDLE_CLOSING)) {
|
||||
uv_tcp_queue_accept(server, req);
|
||||
/* Check if we're in a middle of changing the number of pending accepts. */
|
||||
if (!(server->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING)) {
|
||||
uv_tcp_queue_accept(server, req);
|
||||
} else {
|
||||
/* We better be switching to a single pending accept. */
|
||||
assert(server->flags & UV_HANDLE_TCP_SINGLE_ACCEPT);
|
||||
|
||||
server->processed_accepts++;
|
||||
|
||||
if (server->processed_accepts >= uv_simultaneous_server_accepts) {
|
||||
server->processed_accepts = 0;
|
||||
/*
|
||||
* All previously queued accept requests are now processed.
|
||||
* We now switch to queueing just a single accept.
|
||||
*/
|
||||
uv_tcp_queue_accept(server, &server->accept_reqs[0]);
|
||||
server->flags &= ~UV_HANDLE_TCP_ACCEPT_STATE_CHANGING;
|
||||
server->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
active_tcp_streams++;
|
||||
@ -1069,3 +1092,37 @@ int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_tcp_multiple_simultaneous_accepts(uv_tcp_t* handle, int enable) {
|
||||
if (handle->flags & UV_HANDLE_CONNECTION) {
|
||||
uv__set_artificial_error(handle->loop, UV_EINVAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check if we're already in the desired mode. */
|
||||
if ((enable && !(handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT)) ||
|
||||
(!enable && handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Don't allow switching from single pending accept to many. */
|
||||
if (enable) {
|
||||
uv__set_artificial_error(handle->loop, UV_ENOTSUP);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check if we're in a middle of changing the number of pending accepts. */
|
||||
if (handle->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
handle->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT;
|
||||
|
||||
/* Flip the changing flag if we have already queueed multiple accepts. */
|
||||
if (handle->flags & UV_HANDLE_LISTENING) {
|
||||
handle->flags |= UV_HANDLE_TCP_ACCEPT_STATE_CHANGING;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user