summaryrefslogtreecommitdiff
path: root/src/connection.h
diff options
context:
space:
mode:
authorAndy Pan <panjf2000@gmail.com>2022-02-22 20:00:37 +0800
committerGitHub <noreply@github.com>2022-02-22 14:00:37 +0200
commit496375fc36134c72461e6fb97f314be3adfd8b68 (patch)
tree936c20b236d949d71bb2d5b4f4df946ccb1a9bf3 /src/connection.h
parente9ae03787e0a2e0484914737f82bfe216f8e9d52 (diff)
downloadredis-496375fc36134c72461e6fb97f314be3adfd8b68.tar.gz
Reduce system calls of write for client->reply by introducing writev (#9934)
There are scenarios where it results in many small objects in the reply list, such as commands heavily using deferred array replies (`addReplyDeferredLen`). E.g. what COMMAND command and CLUSTER SLOTS used to do (see #10056, #7123), but also in case of a transaction or a pipeline of commands that use just one differed array reply. We used to have to run multiple loops along with multiple calls to `write()` to send data back to peer based on the current code, but by means of `writev()`, we can gather those scattered objects in reply list and include the static reply buffer as well, then send it by one system call, that ought to achieve higher performance. In the case of TLS, we simply check and concatenate buffers into one big buffer and send it away by one call to `connTLSWrite()`, if the amount of all buffers exceeds `NET_MAX_WRITES_PER_EVENT`, then invoke `connTLSWrite()` multiple times to avoid a huge massive of memory copies. Note that aside of reducing system calls, this change will also reduce the amount of small TCP packets sent.
Diffstat (limited to 'src/connection.h')
-rw-r--r--src/connection.h14
1 files changed, 14 insertions, 0 deletions
diff --git a/src/connection.h b/src/connection.h
index 07c1d4dd8..dad2e2fd6 100644
--- a/src/connection.h
+++ b/src/connection.h
@@ -32,6 +32,7 @@
#define __REDIS_CONNECTION_H
#include <errno.h>
+#include <sys/uio.h>
#define CONN_INFO_LEN 32
@@ -59,6 +60,7 @@ typedef struct ConnectionType {
void (*ae_handler)(struct aeEventLoop *el, int fd, void *clientData, int mask);
int (*connect)(struct connection *conn, const char *addr, int port, const char *source_addr, ConnectionCallbackFunc connect_handler);
int (*write)(struct connection *conn, const void *data, size_t data_len);
+ int (*writev)(struct connection *conn, const struct iovec *iov, int iovcnt);
int (*read)(struct connection *conn, void *buf, size_t buf_len);
void (*close)(struct connection *conn);
int (*accept)(struct connection *conn, ConnectionCallbackFunc accept_handler);
@@ -142,6 +144,18 @@ static inline int connWrite(connection *conn, const void *data, size_t data_len)
return conn->type->write(conn, data, data_len);
}
+/* Gather output data from the iovcnt buffers specified by the members of the iov
+ * array: iov[0], iov[1], ..., iov[iovcnt-1] and write to connection, behaves the same as writev(3).
+ *
+ * Like writev(3), a short write is possible. A -1 return indicates an error.
+ *
+ * The caller should NOT rely on errno. Testing for an EAGAIN-like condition, use
+ * connGetState() to see if the connection state is still CONN_STATE_CONNECTED.
+ */
+static inline int connWritev(connection *conn, const struct iovec *iov, int iovcnt) {
+ return conn->type->writev(conn, iov, iovcnt);
+}
+
/* Read from the connection, behaves the same as read(2).
*
* Like read(2), a short read is possible. A return value of 0 will indicate the