From: Michal Sojka Date: Tue, 17 Sep 2013 11:43:21 +0000 (+0200) Subject: Add vcanbench tool X-Git-Tag: fix-allnoconfig~131 X-Git-Url: http://rtime.felk.cvut.cz/gitweb/can-benchmark.git/commitdiff_plain/5bcd0741bde353a1b8d920116f2c3cd116b9295c Add vcanbench tool I forgot to commit this tool when I created it yeas ago. If I remember well it can be used to measure performance of vcan interfaces. --- diff --git a/latester/Makefile.omk b/latester/Makefile.omk index 0d1e2be..63db1c2 100644 --- a/latester/Makefile.omk +++ b/latester/Makefile.omk @@ -1,9 +1,12 @@ # -*- makefile -*- -bin_PROGRAMS += latester +bin_PROGRAMS += latester vcanbench latester_SOURCES = latester.c latester_LIBS = rt pthread m talloc popt #ulut +vcanbench_SOURCES = vcanbench.c +vcanbench_LIBS = rt m talloc + INCLUDES = -DSO_RXQ_OVFL=40 \ -DPF_CAN=29 \ -DAF_CAN=PF_CAN diff --git a/latester/vcanbench.c b/latester/vcanbench.c new file mode 100644 index 0000000..9aab186 --- /dev/null +++ b/latester/vcanbench.c @@ -0,0 +1,137 @@ +/*******************************************************/ +/* Simple vcan latency benchmark */ +/* Copyright (C) 2012 Michal Sojka, DCE FEE CTU Prague */ +/* License: GPLv2 */ +/*******************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MEMSET_ZERO(obj) memset(&(obj), 0, sizeof(obj)) + +static inline int sock_get_if_index(int s, const char *if_name) +{ + struct ifreq ifr; + MEMSET_ZERO(ifr); + + strcpy(ifr.ifr_name, if_name); + if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) + error(1, errno, "SIOCGIFINDEX '%s'", if_name); + return ifr.ifr_ifindex; +} + +int create_can_socket(const char *dev) +{ + int s; + struct sockaddr_can addr; + if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) + error(1, errno, "socket"); + + addr.can_family = AF_CAN; + addr.can_ifindex = sock_get_if_index(s, dev); + + if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) + error(1, errno, "bind"); + + return s; +} + +/* Subtract the `struct timespec' values X and Y, storing the result in + RESULT. Return 1 if the difference is negative, otherwise 0. */ + +int timespec_subtract (struct timespec *result, const struct timespec *x, const struct timespec *yy) +{ + struct timespec ylocal = *yy, *y = &ylocal; + /* Perform the carry for the later subtraction by updating Y. */ + if (x->tv_nsec < y->tv_nsec) { + int nsec = (y->tv_nsec - x->tv_nsec) / 1000000000 + 1; + y->tv_nsec -= 1000000000 * nsec; + y->tv_sec += nsec; + } + if (x->tv_nsec - y->tv_nsec > 1000000000) { + int nsec = (x->tv_nsec - y->tv_nsec) / 1000000000; + y->tv_nsec += 1000000000 * nsec; + y->tv_sec -= 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; + + /* Return 1 if result is negative. */ + return x->tv_sec < y->tv_sec; +} + +unsigned long timespec_diff_ns(const struct timespec *x, const struct timespec *y) +{ + struct timespec r; + timespec_subtract(&r, x, y); + return r.tv_sec*1000000000 + r.tv_nsec; +} + +#define CHKERR(expr) ({ int __ret = (expr); if (__ret == -1) error(1, errno, #expr); __ret; }) + +static int cmp(const void *p1, const void *p2) +{ + return *(unsigned long*)p1 - *(unsigned long*)p2; +} + +int main(int argc, char *argv[]) +{ + const char *dev; + long count; + int s1, s2; + + if (argc < 2) { + fprintf(stderr, "Usage: %s [ ]\n", argv[0]); + exit(1); + } + dev = argv[1]; + count = argc > 2 ? atol(argv[2]) : -1; + + CHKERR(s1 = create_can_socket(dev)); + CHKERR(s2 = create_can_socket(dev)); + + unsigned long *ns = NULL; + + if (count > 0) + ns = malloc(count*sizeof(*ns)); + + unsigned long i; + for (i = 0; count == -1 || i < count; i++) { + struct can_frame f1 = { .can_id = 0x123, .can_dlc = 8 }, f2; + struct timespec t1, t2; + + clock_gettime(CLOCK_MONOTONIC, &t1); + CHKERR(write(s1, &f1, sizeof(f1))); + CHKERR(read(s2, &f2, sizeof(f2))); + clock_gettime(CLOCK_MONOTONIC, &t2); + unsigned long delay = timespec_diff_ns(&t2, &t1); + if (count >= 0) { + ns[i] = delay; + } else + printf("delay %lu ns\n", delay); + } + + if (ns) { + unsigned long long sum = 0; + for (i = 0; i < count; i++) + sum += ns[i]; + printf("avg=%lld [ns]\n", sum/count); + + qsort(ns, count, sizeof(*ns), cmp); + printf("percentiles: 0th:%ld 25th:%d 50th:%d 75th:%d 100th:%d\n", + ns[0], ns[count/4], ns[count/2], ns[count*3/4], ns[count-1]); + } + + return 0; +}