Created
January 20, 2022 08:40
-
-
Save mathis-m/fa7cb0e6e22191e23c11902a19f6db1c to your computer and use it in GitHub Desktop.
This file contains hidden or 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
#define _CRT_SECURE_NO_WARNINGS | |
#define _GNU_SOURCE | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <sys/time.h> | |
#include <stdbool.h> | |
#include <fcntl.h> | |
#include <time.h> | |
//https://linux.die.net/man/7/pipe#:~:text=Since%20Linux%202.6.11%2C%20the%20pipe%20capacity%20is%2065536%20bytes | |
double getDifferenceTimeOfDay(struct timeval *begin, struct timeval *end) { | |
return ((end->tv_sec - begin->tv_sec) + ((end->tv_usec - begin->tv_usec) / (1000.0 * 1000.0))); | |
} | |
int main(int argc, char *argv[]) { | |
// get arguments passed | |
bool logToConsole = atoi(argv[1]); | |
int count = atoi(argv[2]); | |
bool aufgabe2 = atoi(argv[3]); | |
FILE *fWrite = NULL; | |
FILE *fRead = NULL; | |
FILE *fTotalTime = NULL; | |
if (logToConsole == false) { | |
// setup file headers (mode w => file wird überschrieben) | |
fWrite = fopen("write.csv", "w"); | |
if (fWrite == NULL) { | |
printf("Error opening file!\n"); | |
exit(1); | |
} | |
fprintf(fWrite, "Size,Throughput,Precise Throughput\n"); | |
fclose(fWrite); | |
fRead = fopen("read.csv", "w"); | |
if (fRead == NULL) { | |
printf("Error opening file!\n"); | |
exit(1); | |
} | |
fprintf(fRead, "Size,Throughput,Precise Throughput\n"); | |
fclose(fRead); | |
fTotalTime = fopen("total-time.csv", "w"); | |
if (fTotalTime == NULL) { | |
printf("Error opening file!\n"); | |
exit(1); | |
} | |
fprintf(fTotalTime, "Size,Total Time, Precise Total Time\n"); | |
fclose(fTotalTime); | |
} | |
// for 16, 64, 256, ... 16MiB | |
for (int size = 16; size <= 16 * 1024 * 1024; size *= 4) { | |
printf("\n\n=== Buffer Size %d ===\n", size); | |
int pipefd[2] = {0}; | |
int pipefdBack[2] = {0}; | |
char *buf; | |
char *buf2; | |
buf = malloc(size); | |
buf2 = malloc(size); | |
double mbPerS, totalTimeTaken, preciseThroughput, preciseTotalTimeTaken; | |
if (buf == NULL) { | |
perror("malloc"); | |
return 1; | |
} | |
// Create Parent2Child Pipe | |
if (pipe(pipefd) == -1) { | |
perror("pipe"); | |
return 1; | |
} | |
fcntl(pipefd[1], F_SETPIPE_SZ, size); | |
// printf("Pipe Size is %d\n", pipeSize); | |
// Create Child2Parent Pipe | |
if (pipe(pipefdBack) == -1) { | |
perror("pipe"); | |
return 1; | |
} | |
fcntl(pipefdBack[1], F_SETPIPE_SZ, size); | |
// printf("Pipe Size is %d\n", pipeSize); | |
// Split process to Parent and Child Process | |
if (fork() == 0) { | |
struct timeval readStart, readEnd; | |
struct timespec readStartPrecise, readEndPrecise; | |
bool started = false; | |
// child Process | |
for (int i = 0; i < count; i++) { | |
int totalCount = 0; | |
while (totalCount < size) { | |
int readByteCount = read(pipefd[0], buf + totalCount, size - totalCount); | |
totalCount += readByteCount; | |
if (readByteCount == -1) { | |
perror("read"); | |
return 1; | |
} | |
} | |
if (aufgabe2 == true) { | |
size_t bytesWritten = write(pipefdBack[1], buf2, size); | |
if (bytesWritten != size) { | |
fprintf(stderr, "write2 size did not match: %zu bytes were written.\n", bytesWritten); | |
return 1; | |
} | |
} | |
if (started == false) { | |
gettimeofday(&readStart, NULL); | |
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &readStartPrecise); | |
started = true; | |
} | |
if (totalCount != size) { | |
printf("[%d] size error, expected: %d bytes but got %d\n", i, size, totalCount); | |
return 1; | |
} | |
} | |
gettimeofday(&readEnd, NULL); | |
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &readEndPrecise); | |
long diffInNanos = (readEndPrecise.tv_sec - readStartPrecise.tv_sec) * (long) 1e9 + | |
(readEndPrecise.tv_nsec - readStartPrecise.tv_nsec); | |
double diffInS = (diffInNanos / 1e9); | |
double measuredBytes = (count - 1) * (double) size; | |
double preciseThroughput = measuredBytes / ((double) diffInS * 1024 * 1024); | |
// check how long it has taken to send data to child process | |
double timeTaken = getDifferenceTimeOfDay(&readStart, &readEnd); | |
// calc total bytes send per time in MiB/s | |
double readThroughtput = ((double) (count - 1) * size) / ((double) timeTaken * 1024 * 1024); | |
sleep(1); | |
printf("\tRead:\n\t\tThroughput: %f MiB/s\n\t\tPrecise Throughput: %f MiB/s\n", | |
readThroughtput, preciseThroughput); | |
if (logToConsole == false) { | |
fRead = fopen("read.csv", "a"); | |
if (fRead == NULL) { | |
printf("Error opening file!\n"); | |
exit(1); | |
} | |
fprintf(fRead, "%d,%f,%f\n", size, readThroughtput, preciseThroughput); | |
fclose(fRead); | |
} | |
return 0; | |
} else { | |
// parent process | |
struct timeval begin, end, totalBegin, endTotal; | |
struct timespec beginPrecise, endPrecise, beginTotalPrecise, endTotalPrecise; | |
// check how long it has taken to send data to child process | |
double timeTaken = 0; | |
double timeTakenPrecise = 0; | |
// set begin times | |
gettimeofday(&totalBegin, NULL); | |
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &beginTotalPrecise); | |
// send data to child process | |
for (int i = 0; i < count; i++) { | |
gettimeofday(&begin, NULL); | |
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &beginPrecise); | |
// actual call to send data via pipe | |
size_t bytesWritten = write(pipefd[1], buf, size); | |
gettimeofday(&end, NULL); | |
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &endPrecise); | |
timeTaken += getDifferenceTimeOfDay(&begin, &end); | |
long diffInNanos = (endPrecise.tv_sec - beginPrecise.tv_sec) * (long) 1e9 + | |
(endPrecise.tv_nsec - beginPrecise.tv_nsec); | |
timeTakenPrecise += diffInNanos / 1e9; | |
// for benchmark it makes sense to check if the size of bytes written to the pipe is the expected size | |
if (bytesWritten != size) { | |
fprintf(stderr, "write size did not match: %zu bytes were written.\n", bytesWritten); | |
return 1; | |
} | |
if (aufgabe2 == true) { | |
// read from pipe 2 | |
int totalCount = 0; | |
while (totalCount < size) { | |
int readByteCount = read(pipefdBack[0], buf2 + totalCount, size - totalCount); | |
totalCount += readByteCount; | |
if (readByteCount == -1) { | |
perror("read"); | |
return 1; | |
} | |
} | |
if (totalCount != size) { | |
printf("[%d] size error, expected: %d bytes but got %d\n", i, size, totalCount); | |
return 1; | |
} | |
} | |
} | |
gettimeofday(&endTotal, NULL); | |
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &endTotalPrecise); | |
// get total avg time it has taken: parent -> child -> parent | |
totalTimeTaken = getDifferenceTimeOfDay(&totalBegin, &endTotal) / count; | |
long diffInNanos = (endTotalPrecise.tv_sec - beginTotalPrecise.tv_sec) * (long) 1e9 + | |
(endTotalPrecise.tv_nsec - beginTotalPrecise.tv_nsec); | |
preciseTotalTimeTaken = ((double)diffInNanos / 1e9) / count; | |
// calc total bytes send per time in MiB/s | |
double measuredBytes = count * (double) size; | |
mbPerS = measuredBytes / ((double) timeTaken * 1024 * 1024); | |
preciseThroughput = measuredBytes / ((double) timeTakenPrecise * 1024 * 1024); | |
} | |
// log for current size, durchsatz und total time taken | |
if (aufgabe2 == true) { | |
printf("\tRound Trip:\n\t\tTime: %fs\n\t\tPrecise Time: %fs\n", | |
totalTimeTaken, preciseTotalTimeTaken); | |
} | |
printf("\tWrite:\n\t\tThroughput: %f MiB/s\n\t\tPrecise Throughput: %f MiB/s\n", | |
mbPerS, preciseThroughput); | |
if (logToConsole == false) { | |
// open file in append mode | |
fWrite = fopen("write.csv", "a"); | |
if (fWrite == NULL) { | |
printf("Error opening file!\n"); | |
exit(1); | |
} | |
fprintf(fWrite, "%d,%f,%f\n", size, mbPerS, preciseThroughput); | |
fclose(fWrite); | |
fTotalTime = fopen("total-time.csv", "a"); | |
if (fTotalTime == NULL) { | |
printf("Error opening file!\n"); | |
exit(1); | |
} | |
fprintf(fTotalTime, "%d,%f,%f\n", size, totalTimeTaken, preciseTotalTimeTaken); | |
fclose(fTotalTime); | |
} | |
sleep(2); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment