haproxy/src
Willy Tarreau 8dbd1a2e09 MINOR: connection: avoid a useless recvfrom() on outgoing connections
When a connect() doesn't immediately succeed (i.e. most of the times),
fd_cant_send() is called to enable polling. But given that we don't
mark that we cannot receive either, we end up performing a failed
recvfrom() immediately when the connect() is finally confirmed, as
indicated in issue #253.

This patch simply adds fd_cant_recv() as well so that we're only
notified once the recv path is ready. The reason it was not there
is purely historic, as in the past when there was the fd cache,
doing it would have caused a pending recv request to be placed into
the fd cache, hence a useless recvfrom() upon success (i.e. what
happens now).

Without this patch, forwarding 100k connections does this:

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 17.51    0.704229           7    100000    100000 connect
 16.75    0.673875           3    200000           sendto
 16.24    0.653222           3    200036           close
 10.82    0.435082           1    300000    100000 recvfrom
 10.37    0.417266           1    300012           setsockopt
  7.12    0.286511           1    199954           epoll_ctl
  6.80    0.273447           2    100000           shutdown
  5.34    0.214942           2    100005           socket
  4.65    0.187137           1    105002      5002 accept4
  3.35    0.134757           1    100004           fcntl
  0.61    0.024585           4      5858           epoll_wait

With the patch:

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 18.04    0.697365           6    100000    100000 connect
 17.40    0.672471           3    200000           sendto
 17.03    0.658134           3    200036           close
 10.57    0.408459           1    300012           setsockopt
  7.69    0.297270           1    200000           recvfrom
  7.32    0.282934           1    199922           epoll_ctl
  7.09    0.274027           2    100000           shutdown
  5.59    0.216041           2    100005           socket
  4.87    0.188352           1    104697      4697 accept4
  3.35    0.129641           1    100004           fcntl
  0.65    0.024959           4      5337         1 epoll_wait

Note the total disappearance of 1/3 of failed recvfrom() *without*
adding any extra syscall anywhere else.

The trace of an HTTP health check is now totally clean, with no useless
syscall at all anymore:

  09:14:21.959255 connect(9, {sa_family=AF_INET, sin_port=htons(8000), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
  09:14:21.959292 epoll_ctl(4, EPOLL_CTL_ADD, 9, {EPOLLIN|EPOLLOUT|EPOLLRDHUP, {u32=9, u64=9}}) = 0
  09:14:21.959315 epoll_wait(4, [{EPOLLOUT, {u32=9, u64=9}}], 200, 1000) = 1
  09:14:21.959376 sendto(9, "OPTIONS / HTTP/1.0\r\ncontent-leng"..., 41, MSG_DONTWAIT|MSG_NOSIGNAL, NULL, 0) = 41
  09:14:21.959436 epoll_wait(4, [{EPOLLOUT, {u32=9, u64=9}}], 200, 1000) = 1
  09:14:21.959456 epoll_ctl(4, EPOLL_CTL_MOD, 9, {EPOLLIN|EPOLLRDHUP, {u32=9, u64=9}}) = 0
  09:14:21.959512 epoll_wait(4, [{EPOLLIN|EPOLLRDHUP, {u32=9, u64=9}}], 200, 1000) = 1
  09:14:21.959548 recvfrom(9, "HTTP/1.0 200\r\nContent-length: 0\r"..., 16320, 0, NULL, NULL) = 126
  09:14:21.959570 close(9)                = 0

With the edge-triggered poller, it gets even better:

  09:29:15.776201 connect(9, {sa_family=AF_INET, sin_port=htons(8000), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
  09:29:15.776256 epoll_ctl(4, EPOLL_CTL_ADD, 9, {EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLET, {u32=9, u64=9}}) = 0
  09:29:15.776287 epoll_wait(4, [{EPOLLOUT, {u32=9, u64=9}}], 200, 1000) = 1
  09:29:15.776320 sendto(9, "OPTIONS / HTTP/1.0\r\ncontent-leng"..., 41, MSG_DONTWAIT|MSG_NOSIGNAL, NULL, 0) = 41
  09:29:15.776374 epoll_wait(4, [{EPOLLIN|EPOLLOUT|EPOLLRDHUP, {u32=9, u64=9}}], 200, 1000) = 1
  09:29:15.776406 recvfrom(9, "HTTP/1.0 200\r\nContent-length: 0\r"..., 16320, 0, NULL, NULL) = 126
  09:29:15.776434 close(9)                = 0

It could make sense to backport this patch to 2.2 and maybe 2.1 after
it has been sufficiently checked for absence of side effects in 2.3-dev,
as some people had reported an extra overhead like in issue #168.
2020-07-31 09:29:36 +02:00
..
51d.c MINOR: 51d: silence a warning about null pointer dereference 2020-07-01 23:27:06 +02:00
acl.c BUG/MINOR: acl: Fix freeing of expr->smp in prune_acl_expr 2020-07-07 16:52:35 +02:00
action.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
activity.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
applet.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
arg.c BUG/MEDIUM: arg: empty args list must be dropped 2020-07-21 15:53:54 +02:00
auth.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
backend.c BUG/MEDIUM: backend: always attach the transport before installing the mux 2020-07-31 08:47:58 +02:00
base64.c REORG: include: move base64.h, errors.h and hash.h from common to to haproxy/ 2020-06-11 10:18:56 +02:00
cache.c MEDIUM: htx: Add a flag on a HTX message when no more data are expected 2020-07-22 16:43:32 +02:00
calltrace.c REORG: include: move time.h from common/ to haproxy/ 2020-06-11 10:18:56 +02:00
cfgparse-global.c MINOR: config: make strict limits enabled by default 2020-07-07 16:52:35 +02:00
cfgparse-listen.c BUG/MEDIUM: resolve: fix init resolving for ring and peers section. 2020-07-21 17:59:20 +02:00
cfgparse-ssl.c WIP/MINOR: ssl: add sample fetches for keylog in frontend 2020-07-06 19:08:03 +02:00
cfgparse.c BUG/MEDIUM: resolve: fix init resolving for ring and peers section. 2020-07-21 17:59:20 +02:00
channel.c BUG/MEDIUM: channel: Be aware of SHUTW_NOW flag when output data are peeked 2020-07-17 10:11:34 +02:00
check.c BUG/MEDIUM: checks: Fix off-by-one in allocation of SMTP greeting cmd 2020-06-12 16:18:02 +02:00
chunk.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
cli.c DOC: Use gender neutral language 2020-07-26 22:35:43 +02:00
compression.c BUILD: compression: make gcc 10 happy with free_zlib() 2020-06-14 08:00:19 +02:00
connection.c MEDIUM: connection: Add private connections synchronously in session server list 2020-07-15 14:08:14 +02:00
da.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
debug.c BUG/MINOR: debug: Don't dump the lua stack if it is not initialized 2020-07-27 09:37:18 +02:00
dgram.c REORG: dgram: rename proto_udp to dgram 2020-06-11 10:18:59 +02:00
dict.c REORG: include: move THREAD_LOCAL and __decl_thread() to compiler.h 2020-06-11 10:18:59 +02:00
dns.c BUG/MEDIUM: dns: Don't yield in do-resolve action on a final evaluation 2020-07-30 09:31:09 +02:00
dynbuf.c REORG: buffer: rename buffer.c to dynbuf.c 2020-06-29 09:26:59 +02:00
eb32sctree.c REORG: ebtree: move the include files from ebtree to include/import/ 2020-06-11 09:31:11 +02:00
eb32tree.c REORG: ebtree: move the include files from ebtree to include/import/ 2020-06-11 09:31:11 +02:00
eb64tree.c REORG: ebtree: move the include files from ebtree to include/import/ 2020-06-11 09:31:11 +02:00
ebimtree.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
ebistree.c REORG: ebtree: move the include files from ebtree to include/import/ 2020-06-11 09:31:11 +02:00
ebmbtree.c REORG: ebtree: move the include files from ebtree to include/import/ 2020-06-11 09:31:11 +02:00
ebpttree.c REORG: ebtree: move the include files from ebtree to include/import/ 2020-06-11 09:31:11 +02:00
ebsttree.c REORG: ebtree: move the include files from ebtree to include/import/ 2020-06-11 09:31:11 +02:00
ebtree.c BUG/MEDIUM: ebtree: use a byte-per-byte memcmp() to compare memory blocks 2020-06-16 11:30:33 +02:00
ev_epoll.c MINOR: debug: add a new DEBUG_FD build option 2020-06-23 10:04:54 +02:00
ev_evports.c MINOR: debug: add a new DEBUG_FD build option 2020-06-23 10:04:54 +02:00
ev_kqueue.c MINOR: debug: add a new DEBUG_FD build option 2020-06-23 10:04:54 +02:00
ev_poll.c MINOR: debug: add a new DEBUG_FD build option 2020-06-23 10:04:54 +02:00
ev_select.c MINOR: debug: add a new DEBUG_FD build option 2020-06-23 10:04:54 +02:00
extcheck.c REORG: include: move the error reporting functions to from log.h to errors.h 2020-06-11 10:18:59 +02:00
fcgi-app.c BUG/MEDIUM: fcgi-app: fix memory leak in fcgi_flt_http_headers 2020-07-15 20:23:29 +02:00
fcgi.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
fd.c MINOR: debug: add a new DEBUG_FD build option 2020-06-23 10:04:54 +02:00
filters.c REORG: include: move cfgparse.h to haproxy/cfgparse.h 2020-06-11 10:18:58 +02:00
flt_http_comp.c CLEANUP: assorted typo fixes in the code and comments 2020-07-06 14:34:32 +02:00
flt_spoe.c MINOR: buffer: use MT_LIST_ADDQ() for buffer_wait lists additions 2020-07-10 08:52:13 +02:00
flt_trace.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
freq_ctr.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
frontend.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
h1.c BUILD: tree-wide: cast arguments to tolower/toupper to unsigned char 2020-07-05 21:50:02 +02:00
h1_htx.c MEDIUM: htx: Add a flag on a HTX message when no more data are expected 2020-07-22 16:43:32 +02:00
h2.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
haproxy.c DOC: Use gender neutral language 2020-07-26 22:35:43 +02:00
hash.c REORG: include: move base64.h, errors.h and hash.h from common to to haproxy/ 2020-06-11 10:18:56 +02:00
hlua.c BUG/MINOR: lua: Fix a possible null pointer deref on lua ctx 2020-07-30 10:40:59 +02:00
hlua_fcn.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
hpack-dec.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
hpack-enc.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
hpack-huff.c REORG: include: move hpack*.h to haproxy/ and split hpack-tbl 2020-06-11 10:18:57 +02:00
hpack-tbl.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
http.c CLEANUP: assorted typo fixes in the code and comments 2020-07-06 14:34:32 +02:00
http_acl.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
http_act.c BUG/MINOR: http_act: don't check capture id in backend (2) 2020-07-03 18:30:54 +02:00
http_ana.c BUG/MEDIUM: http-ana: Only set CF_EXPECT_MORE flag on data filtering 2020-07-22 16:46:37 +02:00
http_conv.c CLEANUP: assorted typo fixes in the code and comments 2020-07-06 14:34:32 +02:00
http_fetch.c CLEANUP: assorted typo fixes in the code and comments 2020-07-06 14:34:32 +02:00
http_htx.c CLEANUP: assorted typo fixes in the code and comments 2020-06-26 11:27:28 +02:00
http_rules.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
htx.c CLEANUP: assorted typo fixes in the code and comments 2020-07-06 14:34:32 +02:00
lb_chash.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
lb_fas.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
lb_fwlc.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
lb_fwrr.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
lb_map.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
listener.c MINOR: lists: rename some MT_LIST operations to clarify them 2020-07-10 08:50:41 +02:00
log.c MINOR: log: adds counters on received syslog messages. 2020-07-15 17:50:12 +02:00
lru.c MINOR: lru: new function to delete <nb> least recently used keys 2016-01-11 07:31:35 +01:00
mailers.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
map.c MEDIUM: map: make the "clear map" operation yield 2020-06-19 16:57:51 +02:00
mux_fcgi.c BUG/MINOR: mux-fcgi: Don't url-decode the QUERY_STRING parameter anymore 2020-07-23 15:44:39 +02:00
mux_h1.c BUG/MEDIUM: mux-h1: Continue to process request when switching in tunnel mode 2020-07-15 14:08:14 +02:00
mux_h2.c MEDIUM: htx: Add a flag on a HTX message when no more data are expected 2020-07-22 16:43:32 +02:00
mux_pt.c MINOR: connection: Set the conncetion target during its initialisation 2020-07-15 14:08:14 +02:00
mworker-prog.c REORG: include: move the error reporting functions to from log.h to errors.h 2020-06-11 10:18:59 +02:00
mworker.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
namespace.c REORG: include: move the error reporting functions to from log.h to errors.h 2020-06-11 10:18:59 +02:00
pattern.c BUILD: tree-wide: cast arguments to tolower/toupper to unsigned char 2020-07-05 21:50:02 +02:00
payload.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
peers.c CLEANUP: assorted typo fixes in the code and comments 2020-07-06 14:34:32 +02:00
pipe.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
pool.c MINOR: pools: move the LRU cache heads to thread_info 2020-06-29 10:36:37 +02:00
proto_sockpair.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
proto_tcp.c MINOR: connection: avoid a useless recvfrom() on outgoing connections 2020-07-31 09:29:36 +02:00
proto_udp.c MINOR: log: adds syslog udp message handler and parsing. 2020-07-15 17:50:12 +02:00
proto_uxst.c MINOR: connection: avoid a useless recvfrom() on outgoing connections 2020-07-31 09:29:36 +02:00
protocol.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
proxy.c BUILD: tcp: condition TCP keepalive settings to platforms providing them 2020-07-09 05:58:51 +02:00
queue.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
raw_sock.c MINOR: raw_sock: Report the number of bytes emitted using the splicing 2020-07-15 14:08:14 +02:00
regex.c CLEANUP: assorted typo fixes in the code and comments 2020-07-06 14:34:32 +02:00
ring.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
sample.c MEDIUM: log/sink: re-work and merge of build message API. 2020-07-15 17:50:12 +02:00
server.c BUG/MAJOR: dns: fix null pointer dereference in snr_update_srv_status 2020-07-29 12:05:55 +02:00
session.c MINOR: connection: Set the conncetion target during its initialisation 2020-07-15 14:08:14 +02:00
sha1.c BUILD: use inttypes.h instead of stdint.h 2019-04-01 07:44:56 +02:00
shctx.c REORG: include: split global.h into haproxy/global{,-t}.h 2020-06-11 10:18:58 +02:00
signal.c REORG: include: move the error reporting functions to from log.h to errors.h 2020-06-11 10:18:59 +02:00
sink.c BUG/MEDIUM: resolve: fix init resolving for ring and peers section. 2020-07-21 17:59:20 +02:00
ssl_ckch.c CLEANUP: assorted typo fixes in the code and comments 2020-07-06 14:34:32 +02:00
ssl_crtlist.c MINOR: cli/ssl: handle trailing slashes in crt-list commands 2020-06-25 15:40:10 +02:00
ssl_sample.c CLEANUP: ssl: remove unrelevant comment in smp_fetch_ssl_x_keylog() 2020-07-07 16:14:08 +02:00
ssl_sock.c MINOR: connection: use MT_LIST_ADDQ() to add connections to idle lists 2020-07-10 08:52:13 +02:00
ssl_utils.c REORG: include: move ssl_sock.h to haproxy/ssl_sock{,-t}.h 2020-06-11 10:18:58 +02:00
stats.c MEDIUM: htx: Add a flag on a HTX message when no more data are expected 2020-07-22 16:43:32 +02:00
stick_table.c CLEANUP: assorted typo fixes in the code and comments 2020-06-26 11:27:28 +02:00
stream.c MEDIUM: tcp-rules: Use a dedicated expiration date for tcp ruleset 2020-07-30 09:31:09 +02:00
stream_interface.c MINOR: stream-int: Be sure to have a mux to do sends and receives 2020-07-30 09:39:20 +02:00
task.c MINOR: tasks/debug: add a few BUG_ON() to detect use of wrong timer queue 2020-07-22 14:42:52 +02:00
tcp_rules.c MEDIUM: tcp-rules: Use a dedicated expiration date for tcp ruleset 2020-07-30 09:31:09 +02:00
tcpcheck.c BUG/MEDIUM: tcp-checks: always attach the transport before installing the mux 2020-07-31 08:49:31 +02:00
thread.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
time.c CLEANUP: assorted typo fixes in the code and comments 2020-07-06 14:34:32 +02:00
tools.c BUILD: tools: fix build with static only toolchains 2020-07-24 13:55:40 +02:00
trace.c MEDIUM: log/sink: re-work and merge of build message API. 2020-07-15 17:50:12 +02:00
uri_auth.c REORG: include: move the error reporting functions to from log.h to errors.h 2020-06-11 10:18:59 +02:00
vars.c CLEANUP: Add static void vars_deinit() 2020-07-07 16:52:35 +02:00
version.c BUILD: Fix build by including haproxy/global.h 2020-06-16 23:36:04 +02:00
wdt.c REORG: include: move the error reporting functions to from log.h to errors.h 2020-06-11 10:18:59 +02:00
wurfl.c CLEANUP: include: tree-wide alphabetical sort of include files 2020-06-11 10:18:59 +02:00
xprt_handshake.c REORG: include: move stream_interface.h to haproxy/stream_interface{,-t}.h 2020-06-11 10:18:58 +02:00
xxhash.c BUILD: use inttypes.h instead of stdint.h 2019-04-01 07:44:56 +02:00