Add sendmmsg benchamark
authorMichal Sojka <sojkam1@fel.cvut.cz>
Mon, 20 Jan 2014 14:09:02 +0000 (15:09 +0100)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Mon, 20 Jan 2014 14:09:02 +0000 (15:09 +0100)
recvmmsg/bench.sh
recvmmsg/can_recvmmsg.c
recvmmsg/plot.gp
recvmmsg/ppc/boot
recvmmsg/ppc/mkinitramfs [deleted file]

index faaf8d0..f144167 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-echo "Running can_recvmmsg benchmark"
+echo >&2 "Running can_recvmmsg benchmark"
 
 PATH=../_compiled/bin:$PATH
 
@@ -15,6 +15,6 @@ for i in $COUNTS; do
 #    for j in $(seq 10); do
        tr=$(can_recvmmsg -q -c $i -r)
        tm=$(can_recvmmsg -q -c $i -m)
-       echo $i $tr $tm
+       printf "%-5d %s\n" $i "$tr $tm"
 #    done
 done
index 4dee5f1..7e21c65 100644 (file)
 #include <time.h>
 #include <stdbool.h>
 
-#define CHECK(cmd) do { if ((cmd) == -1) { perror(#cmd); exit(1); } } while (0)
+#define STRINGIFY(val) #val
+#define TOSTRING(val) STRINGIFY(val)
+#define CHECK(cmd) ({ int ret = (cmd); if (ret == -1) { perror(#cmd " line " TOSTRING(__LINE__)); exit(1); }; ret; })
 
 char *dev = "vcan0";
 int count = 10000;
-enum { READ, RECVMMSG } recv_method = READ;
+enum { READWRITE, MMSG } method = READWRITE;
 bool quiet = false;
 
 /* Subtract the `struct timespec' values X and Y,
@@ -29,25 +31,18 @@ bool quiet = false;
 
 int
 timespec_subtract (struct timespec *result,
-                  struct timespec *x,
-                  struct timespec *y)
+                  const struct timespec *x,
+                  const 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;
-       }
+       int carry = (x->tv_nsec < y->tv_nsec);
+
+       result->tv_sec = x->tv_sec - y->tv_sec - carry;
+       result->tv_nsec = x->tv_nsec + carry*1000000000 - y->tv_nsec;
 
-       /* 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;
+/*     printf("%ld.%09ld - %ld.%09ld = %ld.%09ld\n", */
+/*            x->tv_sec, x->tv_nsec, */
+/*            y->tv_sec, y->tv_nsec, */
+/*            result->tv_sec, result->tv_nsec); */
 
        /* Return 1 if result is negative. */
        return x->tv_sec < y->tv_sec;
@@ -61,7 +56,7 @@ void benchmark()
        struct ifreq ifr;
        struct can_frame cf;
        int ret, i;
-       struct timespec t, t1, t2;
+       struct timespec ttx, trx, t1, t2;
 
        ss = socket(PF_CAN, SOCK_RAW, CAN_RAW);
        sr = socket(PF_CAN, SOCK_RAW, CAN_RAW);
@@ -81,17 +76,43 @@ void benchmark()
        memset(&cf, 0, sizeof(cf));
        cf.can_dlc = 8;
 
-       if (!quiet) fprintf(stderr, "Sending %d frames\n", count);
-       for (i = 0; i < count; i++) {
-               ret = write(ss, &cf, sizeof(cf));
-               if (ret != sizeof(cf)) {
-                       perror("write");
-                       exit(1);
+       switch (method) {
+       case READWRITE: {
+               if (!quiet) fprintf(stderr, "Sending %d frames via write()\n", count);
+               clock_gettime(CLOCK_MONOTONIC, &t1);
+               for (i = 0; i < count; i++) {
+                       ret = write(ss, &cf, sizeof(cf));
+                       if (ret != sizeof(cf)) {
+                               perror("write");
+                               exit(1);
+                       }
                }
+               clock_gettime(CLOCK_MONOTONIC, &t2);
+               break;
+       }
+       case MMSG: {
+               if (!quiet) fprintf(stderr, "Sending %d frames via sendmmsg()\n", count);
+               struct mmsghdr msgs[count];
+               struct iovec iovecs[count];
+               memset(msgs, 0, sizeof(msgs));
+               memset(iovecs, 0, sizeof(iovecs));
+               for (i = 0; i < count; i++) {
+                       iovecs[i].iov_base         = &cf;
+                       iovecs[i].iov_len          = sizeof(cf);
+                       msgs[i].msg_hdr.msg_iov    = &iovecs[i];
+                       msgs[i].msg_hdr.msg_iovlen = 1;
+               }
+               clock_gettime(CLOCK_MONOTONIC, &t1);
+               for (i = 0; i < count; i += ret)
+                       ret = CHECK(sendmmsg(ss, &msgs[i], count - i, 0));
+               clock_gettime(CLOCK_MONOTONIC, &t2);
+               break;
+       }
        }
+       timespec_subtract(&ttx, &t2, &t1);
 
-       switch (recv_method) {
-       case READ: {
+       switch (method) {
+       case READWRITE: {
                if (!quiet) fprintf(stderr, "Receiving %d frames with read()\n", count);
                clock_gettime(CLOCK_MONOTONIC, &t1);
                for (i = 0; i < count; i++) {
@@ -106,7 +127,7 @@ void benchmark()
                //fprintf(stderr, "\n");
                break;
        }
-       case RECVMMSG: {
+       case MMSG: {
                if (!quiet) fprintf(stderr, "Receiving %d frames with recvmmsg()\n", count);
                struct mmsghdr msgs[count];
                struct iovec iovecs[count];
@@ -133,8 +154,9 @@ void benchmark()
                break;
        }
        }
-       timespec_subtract(&t, &t2, &t1);
-       printf("%d us\n", t.tv_nsec/1000);
+       timespec_subtract(&trx, &t2, &t1);
+       printf("tx %ld rx %ld [us]\n", ttx.tv_sec*1000000 + ttx.tv_nsec/1000,
+                                      trx.tv_sec*1000000 + trx.tv_nsec/1000);
 }
 
 int main(int argc, char *argv[])
@@ -147,10 +169,10 @@ int main(int argc, char *argv[])
                        count = atoi(optarg);
                        break;
                case 'm':
-                       recv_method = RECVMMSG;
+                       method = MMSG;
                        break;
                case 'r':
-                       recv_method = READ;
+                       method = READWRITE;
                        break;
                case 'q':
                        quiet = true;
index 19e18b4..12065f6 100644 (file)
@@ -2,26 +2,45 @@
 set grid
 
 set xlabel "Frames [×1000]"
-set ylabel "Time [ms]"
+set ylabel "RX Time [ms]"
+set y2label "TX Time [ms]"
+set y2tics
 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
+fit ard*x+brd "data" using 1:5  via ard, brd
+fit arm*x+brm "data" using 1:10 via arm, brm
+
+fit awr*x+bwr "data" using 1:3 via awr, bwr
+fit asm*x+bsm "data" using 1:8 via asm, bsm
 
 set yrange [0:]
+set y2range [0:]
+
+brd=brd/1000
+brm=brm/1000
+bwr=bwr/1000
+bsm=bsm/1000
 
-b1=b1/1000
-b2=b2/1000
+plot 'data' using ($1/1000):($5/1000)  lc 1 title 'read()', \
+     'data' using ($1/1000):($10/1000) lc 1 title 'recvmmsg()', \
+     'data' using ($1/1000):($3/1000) lc 2 axes x1y2 title 'write()', \
+     'data' using ($1/1000):($8/1000) lc 2 axes x1y2 title 'sendmmsg()', \
+     ard*x+brd with lines lt 1 lc rgbcolor "#aa0000" lw 1 title "", \
+     arm*x+brm with lines lt 2 lc rgbcolor "#aa0000" lw 1 title "", \
+     awr*x+bwr with lines axes x1y2 lt 1 lc rgbcolor "#00aa00" lw 1 title "", \
+     asm*x+bsm with lines axes x1y2 lt 2 lc rgbcolor "#00aa00" lw 1 title ""
 
-plot 'data' using ($1/1000):($2/1000) title 'read()', \
-     'data' using ($1/1000):($4/1000) title 'recvmmsg()', \
-     a1*x+b1 with lines lt 1 lc rgbcolor "#aa0000" lw 5 title "", \
-     a2*x+b2 with lines lt 1 lc rgbcolor "#00aa00" lw 5 title ""
+# aread*x+bread - arecv*x-brecv = 0
+# (aread-arecv)*x = brecv-bread
+xeq = (brm-brd)/(ard-arm)
+print "ard = ", ard
+print "arm = ", arm
+print "arm/ard = ", arm/ard
+print "Intersection at x = ", xeq
+print ""
 
-# 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
+xeq = (bsm-bwr)/(awr-asm)
+print "awr = ", awr
+print "asm = ", asm
+print "asm/awr = ", asm/awr
 print "Intersection at x = ", xeq
index 4880855..0188252 100755 (executable)
@@ -3,4 +3,5 @@
 EXITON=Welcome to Buildroot
 load uImage console=ttyPSC0,115200
 load shark-ryu.dtb
-load rootfs2.uImage < $SRCDIR/mkinitramfs
+load rootfsmmsg.uImage < gen_cpio --mkimage="-T ramdisk -A powerpc -O linux" \
+                        rootfs.cpio "$SRCDIR/../bench.sh->/etc/init.d/S50benchmark" "can_recvmmsg->/bin/"
diff --git a/recvmmsg/ppc/mkinitramfs b/recvmmsg/ppc/mkinitramfs
deleted file mode 100755 (executable)
index c6b4f31..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/sh
-
-SRCDIR=${SRCDIR:-$(dirname $0)}
-
-tmpcpio=$(mktemp)
-catcpio=$(mktemp)
-uimage=$(mktemp)
-
-gen_init_cpio - <<EOF > $tmpcpio
-dir /etc 0755 0 0
-dir /etc/init.d 0755 0 0
-file /etc/init.d/S50benchmark $SRCDIR/../bench.sh 0755 0 0
-dir /bin 0755 0 0
-file /bin/can_recvmmsg can_recvmmsg 0755 0 0
-EOF
-
-cat $SRCDIR/rootfs.cpio $tmpcpio > $catcpio
-mkimage -T ramdisk -A powerpc -O linux -d $catcpio $uimage >&2
-cat $uimage
-
-rm $catcpio $tmpcpio $uimage