Finish recvmmsg() benchmark
authorMichal Sojka <sojkam1@fel.cvut.cz>
Mon, 6 Jan 2014 12:39:13 +0000 (13:39 +0100)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Mon, 6 Jan 2014 12:39:13 +0000 (13:39 +0100)
recvmmsg/bench.sh [new file with mode: 0755]
recvmmsg/can_recvmmsg.c
recvmmsg/plot.gp [new file with mode: 0644]

diff --git a/recvmmsg/bench.sh b/recvmmsg/bench.sh
new file mode 100755 (executable)
index 0000000..d2c4742
--- /dev/null
@@ -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
index 9dc57e0..4041f62 100644 (file)
 
 #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 <count>] [-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 (file)
index 0000000..3e0f6dd
--- /dev/null
@@ -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