Skip to content

Instantly share code, notes, and snippets.

@bytbox
Created August 28, 2010 22:01
Show Gist options
  • Save bytbox/555626 to your computer and use it in GitHub Desktop.
Save bytbox/555626 to your computer and use it in GitHub Desktop.
./ipc-speed size iterations port
size The amount of data to transfer, measured in kilobytes.
iterations The number of times to transfer the data. Note that this option
is not to be used to increase the number of trials; the
receiving end of the connection must send a response to the
sender before the transaction is "complete" and the next one
begins, so this should be used to measure latency.
port The port number to operate on, for internet sockets.
/*
* ipc-speed - IPC speed tests
*
*/
#include <limits.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <time.h>
// Chunk size for reading, in bytes.
#define CHUNK 4096
char *argv0;
int size, iterations, port;
unsigned char *data;
int fdatain, fdataout;
int fconfirmin, fconfirmout;
double diff(struct timeval b, struct timeval a) {
double d = b.tv_usec - a.tv_usec;
d += (b.tv_sec - a.tv_sec)*1000000;
return d/1000;
}
void usage() {
printf("usage: %s size iterations port\n", argv0);
exit(2);
}
void generate() {
data = malloc(size*CHUNK);
int i;
for (i = 0; i < size*CHUNK; i++)
data[i] = rand() % UCHAR_MAX;
}
int do_fork() {
int pfd1[2], pfd2[2];
pipe(pfd1);
pipe(pfd2);
fdatain = pfd1[0];
fdataout = pfd1[1];
fconfirmin = pfd2[0];
fconfirmout = pfd2[1];
int pid = fork();
if (pid < 0) {
perror("couldn't fork");
exit(3);
} else if (pid == 0)
return 0;
else
return pid;
}
void transmit(int fdata, int fconfirm) {
int i;
char *buf = malloc(2);
struct timeval start,end;
gettimeofday(&start, 0);
printf("Beginning transaction at %d:%d\n", (int)start.tv_sec, (int)start.tv_usec);
for (i = 0; i < iterations; i++) {
int written;
for (written = 0; written < size; written++) {
write(fdata, data+written*CHUNK, CHUNK);
}
read(fconfirm, buf, 1);
}
gettimeofday(&end, 0);
printf("Transaction completed at %d:%d\n", (int)end.tv_sec, (int)end.tv_usec);
fflush(0);
fprintf(stderr, "%f ms\n", diff(end, start));
fflush(0);
free(buf);
}
void socket_send() {
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr = *(struct in_addr *)(gethostbyname("localhost")->h_addr);
puts("Attempting connection...");
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr))) {
perror("connect");
exit(EXIT_FAILURE);
}
transmit(sock, sock);
}
void receive(int fdata, int fconfirm) {
void *buf = malloc(CHUNK);
char *confirm = malloc(1);
confirm[0] = 0;
int i;
for (i = 0; i < iterations; i++) {
int rc;
for (rc = 0; rc < size; rc++) {
read(fdata, buf, CHUNK);
}
write(fconfirm, confirm, 1);
}
free(buf);
free(confirm);
}
void socket_serve() {
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr))) {
perror("bind");
exit(EXIT_FAILURE);
}
puts("Listening...");
int s = sizeof(addr);
int fd = accept(sock, (struct sockaddr *)&addr, &s);
if (fd < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
receive(fd, fd);
close(fd);
close(sock);
}
int main(int argc, char *argv[]) {
argv0 = argv[0];
if (argc != 4) {
usage();
}
size = strtol(argv[1], 0, 10);
if (size < 1)
usage();
iterations = strtol(argv[2], 0, 10);
if (iterations < 1)
usage();
port = strtol(argv[3], 0, 10);
if (port < 1)
usage();
puts("PIPE IPC");
puts("Generating data...");
generate();
puts("Forking...");
if (!do_fork()) {
receive(fdatain, fconfirmout);
socket_serve();
exit(0);
}
transmit(fdataout, fconfirmin);
sleep(1); // wait for server
puts("\nSOCKET IPC");
socket_send();
return 0;
}
all: ipc-speed
ipc-speed: main.c
cc -g -O0 -o $@ main.c
clean:
rm -f ipc-speed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment