Skip to content

Commit 94c307b

Browse files
committed
Merge bitcoin#30675: http: set TCP_NODELAY when creating HTTP server
03d49d0 http: set TCP_NODELAY when creating HTTP server (Roman Zeyde) Pull request description: Otherwise, the default HTTP server config may result in high latency, due to Nagle's algorithm (on the server) and delayed ACK (on the client): [1] https://www.extrahop.com/blog/tcp-nodelay-nagle-quickack-best-practices [2] https://eklitzke.org/the-caveats-of-tcp-nodelay Without the fix, fetching a small block takes ~40ms (when connection keep-alive is enabled): ``` $ ab -k -c 1 -n 100 http://localhost:8332/rest/block/00000000000002b5898f7cdc80d9c84e9747bc6b9388cc989971d443f05713ee.bin Server Software: Server Hostname: localhost Server Port: 8332 Document Path: /rest/block/00000000000002b5898f7cdc80d9c84e9747bc6b9388cc989971d443f05713ee.bin Document Length: 25086 bytes Concurrency Level: 1 Time taken for tests: 4.075 seconds Complete requests: 100 Failed requests: 0 Keep-Alive requests: 100 Total transferred: 2519200 bytes HTML transferred: 2508600 bytes Requests per second: 24.54 [#/sec] (mean) Time per request: 40.747 [ms] (mean) Time per request: 40.747 [ms] (mean, across all concurrent requests) Transfer rate: 603.76 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.0 0 0 Processing: 0 41 4.1 41 42 Waiting: 0 0 0.1 0 1 Total: 0 41 4.1 41 42 Percentage of the requests served within a certain time (ms) 50% 41 66% 41 75% 41 80% 41 90% 42 95% 42 98% 42 99% 42 100% 42 (longest request) ``` With the fix, it takes ~0.2ms: ``` $ ab -k -c 1 -n 1000 http://localhost:8332/rest/block/00000000000002b5898f7cdc80d9c84e9747bc6b9388cc989971d443f05713ee.bin Benchmarking localhost (be patient) Completed 100 requests Completed 200 requests Completed 300 requests Completed 400 requests Completed 500 requests Completed 600 requests Completed 700 requests Completed 800 requests Completed 900 requests Completed 1000 requests Finished 1000 requests Server Software: Server Hostname: localhost Server Port: 8332 Document Path: /rest/block/00000000000002b5898f7cdc80d9c84e9747bc6b9388cc989971d443f05713ee.bin Document Length: 25086 bytes Concurrency Level: 1 Time taken for tests: 0.194 seconds Complete requests: 1000 Failed requests: 0 Keep-Alive requests: 1000 Total transferred: 25192000 bytes HTML transferred: 25086000 bytes Requests per second: 5147.05 [#/sec] (mean) Time per request: 0.194 [ms] (mean) Time per request: 0.194 [ms] (mean, across all concurrent requests) Transfer rate: 126625.50 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.0 0 0 Processing: 0 0 0.0 0 0 Waiting: 0 0 0.0 0 0 Total: 0 0 0.0 0 0 Percentage of the requests served within a certain time (ms) 50% 0 66% 0 75% 0 80% 0 90% 0 95% 0 98% 0 99% 0 100% 0 (longest request) ``` ACKs for top commit: achow101: ACK 03d49d0 theStack: re-ACK 03d49d0 tdb3: ACK 03d49d0 Tree-SHA512: bbf3d78b8521f569430850ec4315a75711303547df1a3de213a4ad34c9700105e374e0a649352fd05f8e4badb5b59debd3720e1c5d392c5113d7816648f7fcaa
2 parents 27e89bc + 03d49d0 commit 94c307b

File tree

1 file changed

+6
-0
lines changed

1 file changed

+6
-0
lines changed

src/httpserver.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,12 @@ static bool HTTPBindAddresses(struct evhttp* http)
388388
if (i->first.empty() || (addr.has_value() && addr->IsBindAny())) {
389389
LogPrintf("WARNING: the RPC server is not safe to expose to untrusted networks such as the public internet\n");
390390
}
391+
// Set the no-delay option (disable Nagle's algorithm) on the TCP socket.
392+
evutil_socket_t fd = evhttp_bound_socket_get_fd(bind_handle);
393+
int one = 1;
394+
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (sockopt_arg_type)&one, sizeof(one)) == SOCKET_ERROR) {
395+
LogInfo("WARNING: Unable to set TCP_NODELAY on RPC server socket, continuing anyway\n");
396+
}
391397
boundSockets.push_back(bind_handle);
392398
} else {
393399
LogPrintf("Binding RPC on address %s port %i failed.\n", i->first, i->second);

0 commit comments

Comments
 (0)