From: Michal Sojka Date: Mon, 6 Jan 2014 12:39:13 +0000 (+0100) Subject: Finish recvmmsg() benchmark X-Git-Tag: fix-allnoconfig~114 X-Git-Url: http://rtime.felk.cvut.cz/gitweb/can-benchmark.git/commitdiff_plain/c8ace325585de747206daed3291c0b6bb790a81b Finish recvmmsg() benchmark --- diff --git a/recvmmsg/bench.sh b/recvmmsg/bench.sh new file mode 100755 index 0000000..d2c4742 --- /dev/null +++ b/recvmmsg/bench.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +for i in $(octave -q --eval "disp(round(logspace(log10(10), log10(50000), 1000))')"); do +# for j in $(seq 10); do + tr=$(../_compiled/bin/can_recvmmsg -c $i -r) + tm=$(../_compiled/bin/can_recvmmsg -c $i -m) + echo $i $tr $tm +# done +done diff --git a/recvmmsg/can_recvmmsg.c b/recvmmsg/can_recvmmsg.c index 9dc57e0..4041f62 100644 --- a/recvmmsg/can_recvmmsg.c +++ b/recvmmsg/can_recvmmsg.c @@ -17,21 +17,54 @@ #define CHECK(cmd) do { if ((cmd) == -1) { perror(#cmd); exit(1); } } while (0) +char *dev = "vcan0"; int count = 10000; +enum { READ, RECVMMSG } recv_method = READ; -int main(int argc, char *argv[]) +/* Subtract the `struct timespec' values X and Y, + storing the result in RESULT (result = x - y). + Return 1 if the difference is negative, otherwise 0. */ + +int +timespec_subtract (struct timespec *result, + struct timespec *x, + struct timespec *y) +{ + /* Perform the carry for the later subtraction by updating Y. */ + if (x->tv_nsec < y->tv_nsec) { + int num_sec = (y->tv_nsec - x->tv_nsec) / 1000000000 + 1; + y->tv_nsec -= 1000000000 * num_sec; + y->tv_sec += num_sec; + } + if (x->tv_nsec - y->tv_nsec > 1000000000) { + int num_sec = (x->tv_nsec - y->tv_nsec) / 1000000000; + y->tv_nsec += 1000000000 * num_sec; + y->tv_sec -= num_sec; + } + + /* Compute the time remaining to wait. + `tv_nsec' is certainly positive. */ + result->tv_sec = x->tv_sec - y->tv_sec; + result->tv_nsec = x->tv_nsec - y->tv_nsec; + + /* Return 1 if result is negative. */ + return x->tv_sec < y->tv_sec; +} + + +void benchmark() { int ss, sr; struct sockaddr_can addr; struct ifreq ifr; struct can_frame cf; int ret, i; - struct timespec t1, t2; + struct timespec t, t1, t2; ss = socket(PF_CAN, SOCK_RAW, CAN_RAW); sr = socket(PF_CAN, SOCK_RAW, CAN_RAW); - strcpy(ifr.ifr_name, "vcan0" ); + strcpy(ifr.ifr_name, dev); ioctl(ss, SIOCGIFINDEX, &ifr); addr.can_family = AF_CAN; @@ -55,40 +88,79 @@ int main(int argc, char *argv[]) } } -#if 0 - fprintf(stderr, "Receiving %d frames with read()\n", count); - for (i = 0; i < count; i++) { - //fprintf(stderr, "Receiving frame %d\r", i); - ret = read(sr, &cf, sizeof(cf)); - if (ret != sizeof(cf)) { - perror("read"); - exit(1); + switch (recv_method) { + case READ: { + fprintf(stderr, "Receiving %d frames with read()\n", count); + clock_gettime(CLOCK_MONOTONIC, &t1); + for (i = 0; i < count; i++) { + //fprintf(stderr, "Receiving frame %d\r", i); + ret = read(sr, &cf, sizeof(cf)); + if (ret != sizeof(cf)) { + perror("read"); + exit(1); + } } + clock_gettime(CLOCK_MONOTONIC, &t2); + //fprintf(stderr, "\n"); + break; } - //fprintf(stderr, "\n"); -#endif - - fprintf(stderr, "Receiving %d frames with recvmmsg()\n", count); - struct mmsghdr msgs[count]; - struct iovec iovecs[count]; - char bufs[count][sizeof(struct can_frame)]; + case RECVMMSG: { + fprintf(stderr, "Receiving %d frames with recvmmsg()\n", count); + struct mmsghdr msgs[count]; + struct iovec iovecs[count]; + char bufs[count][sizeof(struct can_frame)]; + + memset(msgs, 0, sizeof(msgs)); + for (i = 0; i < count; i++) { + iovecs[i].iov_base = bufs[i]; + iovecs[i].iov_len = sizeof(struct can_frame); + msgs[i].msg_hdr.msg_iov = &iovecs[i]; + msgs[i].msg_hdr.msg_iovlen = 1; + } - memset(msgs, 0, sizeof(msgs)); - for (i = 0; i < count; i++) { - iovecs[i].iov_base = bufs[i]; - iovecs[i].iov_len = sizeof(struct can_frame); - msgs[i].msg_hdr.msg_iov = &iovecs[i]; - msgs[i].msg_hdr.msg_iovlen = 1; + clock_gettime(CLOCK_MONOTONIC, &t1); + ret = recvmmsg(sr, msgs, count, 0, NULL); + clock_gettime(CLOCK_MONOTONIC, &t2); + if (ret == -1) { + perror("recvmmsg()"); + exit(1); + } else if (ret != count) { + fprintf(stderr, "Error: Only %d messages received\n", ret); + exit(1); + } + break; + } } + timespec_subtract(&t, &t2, &t1); + printf("%d us\n", t.tv_nsec/1000); +} - ret = recvmmsg(sr, msgs, count, 0, NULL); - if (ret == -1) { - perror("recvmmsg()"); - exit(1); - } else if (ret != count) { - fprintf(stderr, "Error: Only %d messages received\n", ret); - exit(1); +int main(int argc, char *argv[]) +{ + int opt; + + while ((opt = getopt(argc, argv, "c:mr")) != -1) { + switch (opt) { + case 'c': + count = atoi(optarg); + break; + case 'm': + recv_method = RECVMMSG; + break; + case 'r': + recv_method = READ; + break; + default: /* '?' */ + fprintf(stderr, "Usage: %s [-c ] [-r] [-m] [interface]\n", + argv[0]); + exit(EXIT_FAILURE); + } } + if (optind < argc) + dev = argv[optind]; + + benchmark(); + return 0; } diff --git a/recvmmsg/plot.gp b/recvmmsg/plot.gp new file mode 100644 index 0000000..3e0f6dd --- /dev/null +++ b/recvmmsg/plot.gp @@ -0,0 +1,21 @@ +set grid + +set xlabel "Number of messages" +set ylabel "Time [{/Symbol m}s]" +set key left reverse Left + +fit a1*x+b1 "data" using 1:2 via a1, b1 +fit a2*x+b2 "data" using 1:4 via a2, b2 + +plot 'data' using 1:2 pt 7 ps 0.2 title 'read()', \ + 'data' using 1:4 pt 7 ps 0.2 title 'recvmmsg()', \ + a1*x+b1 with lines lt 1 lc 1 lw 1 title "Linear fit for read()", \ + a2*x+b2 with lines lt 1 lc 2 lw 1 title "Linear fit for recvmmsg()" + +# a1*x+b1 - a2*x-b2 = 0 +# (a1-a2)*x = b2-b1 +xeq = (b2-b1)/(a1-a2) +print "ar = ", a1 +print "am = ", a2 +print "ar/am = ", a1/a2 +print "Intersection at x = ", xeq