Created
October 2, 2023 16:09
-
-
Save Gerold103/edbc7edc75a492a64ade9b8e4898be02 to your computer and use it in GitHub Desktop.
BenchScatterGatherIO
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cassert> | |
#include <cstring> | |
#include <ctime> | |
#include <iostream> | |
#include <thread> | |
#include <netinet/in.h> | |
#include <sys/socket.h> | |
#include <sys/types.h> | |
#include <unistd.h> | |
#define USE_VECTORS 1 | |
static constexpr uint16_t port = 12345; | |
static constexpr int bufCount = 16; | |
static constexpr size_t bufSize = 1024; | |
static constexpr size_t totalBufSize = bufCount * bufSize; | |
static constexpr size_t totalToSend = 15ULL * 1024 * 1024 * 1024; | |
static uint64_t durationUsec = 0; | |
static uint64_t systemCallRecvCount = 0; | |
static uint64_t systemCallSendCount = 0; | |
static uint64_t getUsec() | |
{ | |
timespec t; | |
clock_gettime(CLOCK_MONOTONIC, &t); | |
return t.tv_sec * 1'000'000 + t.tv_nsec / 1000; | |
} | |
static void doSending(int sock) | |
{ | |
uint8_t *data = new uint8_t[totalBufSize]; | |
memset(data, 0, totalBufSize); | |
size_t sent = 0; | |
struct iovec vecs[bufCount]; | |
memset(vecs, 0, sizeof(vecs)); | |
for (int i = 0; i < bufCount; ++i) | |
{ | |
vecs[i].iov_base = data + bufSize * i; | |
vecs[i].iov_len = bufSize; | |
} | |
#if USE_VECTORS | |
msghdr msg; | |
memset(&msg, 0, sizeof(msg)); | |
msg.msg_iov = vecs; | |
msg.msg_iovlen = bufCount; | |
#endif | |
while (sent < totalToSend) | |
{ | |
#if USE_VECTORS | |
++systemCallSendCount; | |
ssize_t rc = sendmsg(sock, &msg, 0); | |
assert(rc > 0); | |
sent += rc; | |
#else | |
for (int i = 0; i < bufCount && sent < totalToSend; ++i) | |
{ | |
++systemCallSendCount; | |
ssize_t rc = send(sock, vecs[i].iov_base, vecs[i].iov_len, 0); | |
assert(rc > 0); | |
sent += rc; | |
} | |
#endif | |
} | |
delete[] data; | |
} | |
static void doReceving(int sock) | |
{ | |
uint8_t *data = new uint8_t[totalBufSize]; | |
memset(data, 0, totalBufSize); | |
size_t received = 0; | |
struct iovec vecs[bufCount]; | |
memset(vecs, 0, sizeof(vecs)); | |
for (int i = 0; i < bufCount; ++i) | |
{ | |
vecs[i].iov_base = data + bufSize * i; | |
vecs[i].iov_len = bufSize; | |
} | |
#if USE_VECTORS | |
msghdr msg; | |
memset(&msg, 0, sizeof(msg)); | |
msg.msg_iov = vecs; | |
msg.msg_iovlen = bufCount; | |
#endif | |
uint64_t t1 = getUsec(); | |
while (received < totalToSend) | |
{ | |
#if USE_VECTORS | |
++systemCallRecvCount; | |
ssize_t rc = recvmsg(sock, &msg, 0); | |
assert(rc > 0); | |
received += rc; | |
#else | |
for (int i = 0; i < bufCount && received < totalToSend; ++i) | |
{ | |
++systemCallRecvCount; | |
ssize_t rc = recv(sock, vecs[i].iov_base, vecs[i].iov_len, 0); | |
assert(rc > 0); | |
received += rc; | |
} | |
#endif | |
} | |
durationUsec = getUsec() - t1; | |
delete[] data; | |
} | |
static void clientF() | |
{ | |
std::cout << "Client is started" << std::endl; | |
sockaddr_in addr; | |
memset(&addr, 0, sizeof(addr)); | |
addr.sin_family = AF_INET; | |
addr.sin_port = htons(port); | |
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); | |
int sock = socket(AF_INET, SOCK_STREAM, 0); | |
assert(sock >= 0); | |
int rc = connect(sock, (sockaddr *)&addr, sizeof(addr)); | |
assert(rc == 0); | |
doReceving(sock); | |
close(sock); | |
std::cout << "Client is finished" << std::endl; | |
} | |
int main() | |
{ | |
std::cout << "Server is started" << std::endl; | |
sockaddr_in addr; | |
memset(&addr, 0, sizeof(addr)); | |
addr.sin_family = AF_INET; | |
addr.sin_port = htons(port); | |
addr.sin_addr.s_addr = htonl(INADDR_ANY); | |
socklen_t len = sizeof(addr); | |
int sock = socket(AF_INET, SOCK_STREAM, 0); | |
assert(sock >= 0); | |
int value = 1; | |
int rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)); | |
assert(rc == 0); | |
rc = bind(sock, (sockaddr *)&addr, len); | |
assert(rc == 0); | |
rc = listen(sock, SOMAXCONN); | |
assert(rc == 0); | |
std::cout << "Receive the data" << std::endl; | |
std::thread clientThread(clientF); | |
int peer = accept(sock, (sockaddr *)&addr, &len); | |
assert(peer >= 0); | |
doSending(peer); | |
std::cout << "Terminate the client" << std::endl; | |
clientThread.join(); | |
close(peer); | |
close(sock); | |
std::cout << "Took " << durationUsec << " us" << std::endl; | |
std::cout << "System calls recv(): " << systemCallRecvCount << std::endl; | |
std::cout << "System calls send(): " << systemCallSendCount << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment