Skip to content

Commit

Permalink
Client: improve operation with iovec
Browse files Browse the repository at this point in the history
Allocate iovec simply on stack.

Don't use NETWORK::readyToRecv anymore, use READAHEAD instead.

Part of #28
  • Loading branch information
alyapunov committed Aug 31, 2022
1 parent f65951d commit 0bcd230
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 63 deletions.
41 changes: 7 additions & 34 deletions src/Client/Connection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
/** rid == request id */
typedef size_t rid_t;

static constexpr size_t CONN_READAHEAD = 64 * 1024;
static constexpr size_t IOVEC_MAX_SIZE = 32;

struct ConnectionError {
std::string msg;
//Saved in case connection fails due to system error.
Expand Down Expand Up @@ -86,9 +89,6 @@ struct ConnectionImpl
Greeting greeting;
bool is_greeting_received;
std::unordered_map<rid_t, Response<BUFFER>> futures;

static constexpr size_t AVAILABLE_IOVEC_COUNT = 32;
struct iovec m_IOVecs[AVAILABLE_IOVEC_COUNT];
};

template<class BUFFER, class NetProvider>
Expand Down Expand Up @@ -172,15 +172,7 @@ class Connection
int getSocket() const;
void setSocket(int socket);
BUFFER& getInBuf();

template<class B, class N>
friend
struct iovec * outBufferToIOV(Connection<B, N> &conn, size_t *iov_len);

template<class B, class N>
friend
struct iovec * inBufferToIOV(Connection<B, N> &conn, size_t size,
size_t *iov_len);
BUFFER& getOutBuf();

template<class B, class N>
friend
Expand Down Expand Up @@ -446,29 +438,10 @@ Connection<BUFFER, NetProvider>::getInBuf()
}

template<class BUFFER, class NetProvider>
struct iovec *
inBufferToIOV(Connection<BUFFER, NetProvider> &conn, size_t size, size_t *iov_len)
{
assert(iov_len != NULL);
BUFFER &buf = conn.impl->inBuf;
struct iovec *vecs = conn.impl->m_IOVecs;
typename BUFFER::iterator itr = buf.end();
buf.write({size});
*iov_len = buf.getIOV(itr, vecs,
ConnectionImpl<BUFFER, NetProvider>::AVAILABLE_IOVEC_COUNT);
return vecs;
}

template<class BUFFER, class NetProvider>
struct iovec *
outBufferToIOV(Connection<BUFFER, NetProvider> &conn, size_t *iov_len)
BUFFER&
Connection<BUFFER, NetProvider>::getOutBuf()
{
assert(iov_len != NULL);
BUFFER &buf = conn.impl->outBuf;
struct iovec *vecs = conn.impl->m_IOVecs;
*iov_len = buf.getIOV(buf.begin(), buf.end(), vecs,
ConnectionImpl<BUFFER, NetProvider>::AVAILABLE_IOVEC_COUNT);
return vecs;
return impl->outBuf;
}

template<class BUFFER, class NetProvider>
Expand Down
29 changes: 12 additions & 17 deletions src/Client/EpollNetProvider.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,21 +189,14 @@ template<class BUFFER, class NETWORK>
int
EpollNetProvider<BUFFER, NETWORK>::recv(Conn_t &conn)
{
size_t total = NETWORK::readyToRecv(conn.getSocket());
if (total < 0) {
LOG_ERROR("Failed to check socket: ioctl returned errno ",
strerror(errno));
return -1;
}
if (total == 0) {
LOG_DEBUG("Socket ", conn.getSocket(), " has no data to read");
return 0;
}
size_t iov_cnt = 0;
/* Get IO vectors array pointing to the input buffer. */
struct iovec *iov = inBufferToIOV(conn, total, &iov_cnt);
auto &buf = conn.getInBuf();
auto itr = buf.template end<true>();
buf.write({CONN_READAHEAD});
struct iovec iov[IOVEC_MAX_SIZE];
size_t iov_cnt = buf.getIOV(itr, iov, IOVEC_MAX_SIZE);

ssize_t rcvd = NETWORK::recvall(conn.getSocket(), iov, iov_cnt, true);
hasNotRecvBytes(conn, total - (rcvd < 0 ? 0 : rcvd));
hasNotRecvBytes(conn, CONN_READAHEAD - (rcvd < 0 ? 0 : rcvd));
if (rcvd < 0) {
//Don't consider EWOULDBLOCK to be an error.
if (netWouldBlock(errno))
Expand Down Expand Up @@ -235,10 +228,12 @@ EpollNetProvider<BUFFER, NETWORK>::send(Conn_t &conn)
{
while (hasDataToSend(conn)) {
size_t sent_bytes = 0;
size_t iov_cnt = 0;
struct iovec *iov = outBufferToIOV(conn, &iov_cnt);
struct iovec iov[IOVEC_MAX_SIZE];
auto &buf = conn.getOutBuf();
size_t iov_cnt = buf.getIOV(buf.template begin<true>(),
iov, IOVEC_MAX_SIZE);
int rc = NETWORK::sendall(conn.getSocket(), iov, iov_cnt,
&sent_bytes);
&sent_bytes);
hasSentBytes(conn, sent_bytes);
if (rc != 0) {
if (netWouldBlock(errno)) {
Expand Down
25 changes: 13 additions & 12 deletions src/Client/LibevNetProvider.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,17 +120,14 @@ template<class BUFFER, class NETWORK>
static inline int
connectionReceive(Connection<BUFFER, LibevNetProvider<BUFFER, NETWORK>> &conn)
{
size_t total = NETWORK::readyToRecv(conn.getSocket());
if (total < 0) {
LOG_ERROR("Failed to check socket: ioctl returned errno ",
strerror(errno));
return -1;
}
size_t iov_cnt = 0;
struct iovec *iov =
inBufferToIOV(conn, total, &iov_cnt);
auto &buf = conn.getInBuf();
auto itr = buf.template end<true>();
buf.write({CONN_READAHEAD});
struct iovec iov[IOVEC_MAX_SIZE];
size_t iov_cnt = buf.getIOV(itr, iov, IOVEC_MAX_SIZE);

ssize_t rcvd = NETWORK::recvall(conn.getSocket(), iov, iov_cnt, true);
hasNotRecvBytes(conn, total - (rcvd < 0 ? 0 : rcvd));
hasNotRecvBytes(conn, CONN_READAHEAD - (rcvd < 0 ? 0 : rcvd));
if (rcvd < 0) {
if (netWouldBlock(errno)) {
return 0;
Expand Down Expand Up @@ -184,8 +181,12 @@ connectionSend(Connection<BUFFER, LibevNetProvider<BUFFER, NETWORK>> &conn)
{
while (hasDataToSend(conn)) {
size_t sent_bytes = 0;
size_t iov_cnt = 0;
struct iovec *iov = outBufferToIOV(conn, &iov_cnt);

struct iovec iov[IOVEC_MAX_SIZE];
auto &buf = conn.getOutBuf();
size_t iov_cnt = buf.getIOV(buf.template begin<true>(),
iov, IOVEC_MAX_SIZE);

int rc = NETWORK::sendall(conn.getSocket(), iov, iov_cnt,
&sent_bytes);
hasSentBytes(conn, sent_bytes);
Expand Down

0 comments on commit 0bcd230

Please sign in to comment.