Commit 2b83af9e87002b77db85a39125ffa971a843aaa2

Authored by Stéphane Raimbault
1 parent 8d1493f9

New programs to benchmark the transfert rate.

The results are really interesting!
- bench-bandwidth-slave.c
- bench-bandwidth-master.c
tests/Makefile.am
1 1 noinst_PROGRAMS = \
2 2 unit-test-master \
3 3 unit-test-slave \
4   - test-master-random
  4 + test-master-random \
  5 + bench-bandwidth-slave \
  6 + bench-bandwidth-master
5 7  
6 8 common_ldflags = \
7 9 $(top_builddir)/modbus/libmodbus.la
... ... @@ -15,5 +17,11 @@ unit_test_slave_LDADD = $(common_ldflags)
15 17 test_master_random_SOURCES = test-master-random.c
16 18 test_master_random_LDADD = $(common_ldflags)
17 19  
  20 +bench_bandwidth_slave_SOURCES = bench-bandwidth-slave.c
  21 +bench_bandwidth_slave_LDADD = $(common_ldflags)
  22 +
  23 +bench_bandwidth_master_SOURCES = bench-bandwidth-master.c
  24 +bench_bandwidth_master_LDADD = $(common_ldflags)
  25 +
18 26 INCLUDES = -I$(top_srcdir)
19 27 CLEANFILES = *~
... ...
tests/bench-bandwidth-master.c 0 → 100644
  1 +/*
  2 + * Copyright © 2008 Stéphane Raimbault <stephane.raimbault@gmail.com>
  3 + *
  4 + * This program is free software: you can redistribute it and/or modify
  5 + * it under the terms of the GNU General Public License as published by
  6 + * the Free Software Foundation; either version 3 of the License, or
  7 + * (at your option) any later version.
  8 + *
  9 + * This program is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 + * GNU General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU General Public License
  15 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16 + */
  17 +
  18 +#include <stdio.h>
  19 +#include <unistd.h>
  20 +#include <string.h>
  21 +#include <stdlib.h>
  22 +#include <time.h>
  23 +#include <sys/time.h>
  24 +
  25 +#include <modbus/modbus.h>
  26 +
  27 +/* Tests based on PI-MBUS-300 documentation */
  28 +#define SLAVE 0x11
  29 +#define NB_LOOPS 1000
  30 +
  31 +#define G_USEC_PER_SEC 1000000
  32 +uint32_t gettime(void)
  33 +{
  34 + struct timeval tv;
  35 + gettimeofday (&tv, NULL);
  36 +
  37 + return (uint32_t) tv.tv_sec * G_USEC_PER_SEC + tv.tv_usec;
  38 +}
  39 +
  40 +int main(void)
  41 +{
  42 + uint8_t *tab_rp_status;
  43 + uint16_t *tab_rp_registers;
  44 + modbus_param_t mb_param;
  45 + int i;
  46 + int ret;
  47 + int nb_points;
  48 + double elapsed;
  49 + uint32_t start;
  50 + uint32_t end;
  51 + uint32_t bytes;
  52 + uint32_t rate;
  53 +
  54 + /* TCP */
  55 + modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
  56 +
  57 + modbus_connect(&mb_param);
  58 +
  59 + /* Allocate and initialize the memory to store the status */
  60 + tab_rp_status = (uint8_t *) malloc(MAX_STATUS * sizeof(uint8_t));
  61 + memset(tab_rp_status, 0, MAX_STATUS * sizeof(uint8_t));
  62 +
  63 + /* Allocate and initialize the memory to store the registers */
  64 + tab_rp_registers = (uint16_t *) malloc(MAX_REGISTERS * sizeof(uint16_t));
  65 + memset(tab_rp_registers, 0, MAX_REGISTERS * sizeof(uint16_t));
  66 +
  67 + printf("READ COIL STATUS\n\n");
  68 +
  69 + nb_points = MAX_STATUS;
  70 + start = gettime();
  71 + for (i=0; i<NB_LOOPS; i++) {
  72 + ret = read_coil_status(&mb_param, SLAVE, 0, nb_points, tab_rp_status);
  73 + }
  74 + end = gettime();
  75 + elapsed = (end - start) / 1000;
  76 +
  77 + rate = (NB_LOOPS * nb_points) * G_USEC_PER_SEC / (end - start);
  78 + printf("Transfert rate in points/seconds:\n");
  79 + printf("* %'d points/s\n", rate);
  80 + printf("\n");
  81 +
  82 + bytes = NB_LOOPS * (nb_points / 8) + ((nb_points % 8) ? 1 : 0);
  83 + rate = bytes / 1024 * G_USEC_PER_SEC / (end - start);
  84 + printf("Values:\n");
  85 + printf("* %d x %d values\n", NB_LOOPS, nb_points);
  86 + printf("* %.3f ms for %d bytes\n", elapsed, bytes);
  87 + printf("* %'d KiB/s\n", rate);
  88 + printf("\n");
  89 +
  90 + /* TCP: Query and reponse header and values */
  91 + bytes = 12 + 9 + (nb_points / 8) + ((nb_points % 8) ? 1 : 0);
  92 + printf("Values and TCP Modbus overhead:\n");
  93 + printf("* %d x %d bytes\n", NB_LOOPS, bytes);
  94 + bytes = NB_LOOPS * bytes;
  95 + rate = bytes / 1024 * G_USEC_PER_SEC / (end - start);
  96 + printf("* %.3f ms for %d bytes\n", elapsed, bytes);
  97 + printf("* %'d KiB/s\n", rate);
  98 + printf("\n\n");
  99 +
  100 + printf("READ HOLDING REGISTERS\n\n");
  101 +
  102 + nb_points = MAX_REGISTERS;
  103 + start = gettime();
  104 + for (i=0; i<NB_LOOPS; i++) {
  105 + ret = read_holding_registers(&mb_param, SLAVE, 0, nb_points, tab_rp_registers);
  106 + }
  107 + end = gettime();
  108 + elapsed = (end - start) / 1000;
  109 +
  110 + rate = (NB_LOOPS * nb_points) * G_USEC_PER_SEC / (end - start);
  111 + printf("Transfert rate in points/seconds:\n");
  112 + printf("* %'d registers/s\n", rate);
  113 + printf("\n");
  114 +
  115 + bytes = NB_LOOPS * nb_points * sizeof(uint16_t);
  116 + rate = bytes / 1024 * G_USEC_PER_SEC / (end - start);
  117 + printf("Values:\n");
  118 + printf("* %d x %d values\n", NB_LOOPS, nb_points);
  119 + printf("* %.3f ms for %d bytes\n", elapsed, bytes);
  120 + printf("* %'d KiB/s\n", rate);
  121 + printf("\n");
  122 +
  123 + /* TCP:Query and reponse header and values */
  124 + bytes = 12 + 9 + (nb_points * sizeof(uint16_t));
  125 + printf("Values and TCP Modbus overhead:\n");
  126 + printf("* %d x %d bytes\n", NB_LOOPS, bytes);
  127 + bytes = NB_LOOPS * bytes;
  128 + rate = bytes / 1024 * G_USEC_PER_SEC / (end - start);
  129 + printf("* %.3f ms for %d bytes\n", elapsed, bytes);
  130 + printf("* %'d KiB/s\n", rate);
  131 + printf("\n");
  132 +
  133 + /* Free the memory */
  134 + free(tab_rp_status);
  135 + free(tab_rp_registers);
  136 +
  137 + /* Close the connection */
  138 + modbus_close(&mb_param);
  139 +
  140 + return 0;
  141 +}
... ...
tests/bench-bandwidth-slave.c 0 → 100644
  1 +/*
  2 + * Copyright © 2008 Stéphane Raimbault <stephane.raimbault@gmail.com>
  3 + *
  4 + * This program is free software: you can redistribute it and/or modify
  5 + * it under the terms of the GNU General Public License as published by
  6 + * the Free Software Foundation; either version 3 of the License, or
  7 + * (at your option) any later version.
  8 + *
  9 + * This program is distributed in the hope that it will be useful,
  10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 + * GNU General Public License for more details.
  13 + *
  14 + * You should have received a copy of the GNU General Public License
  15 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16 + */
  17 +
  18 +#include <stdio.h>
  19 +#include <unistd.h>
  20 +#include <string.h>
  21 +#include <stdlib.h>
  22 +
  23 +#include <modbus/modbus.h>
  24 +
  25 +int main(void)
  26 +{
  27 + int socket;
  28 + modbus_param_t mb_param;
  29 + modbus_mapping_t mb_mapping;
  30 + int ret;
  31 +
  32 + modbus_init_tcp(&mb_param, "127.0.0.1", 1502);
  33 +
  34 + ret = modbus_mapping_new(&mb_mapping, MAX_STATUS, 0, MAX_REGISTERS, 0);
  35 + if (ret == FALSE) {
  36 + printf("Memory allocation failed\n");
  37 + exit(1);
  38 + }
  39 +
  40 + socket = modbus_init_listen_tcp(&mb_param);
  41 +
  42 + while (1) {
  43 + uint8_t query[MAX_MESSAGE_LENGTH];
  44 + int query_size;
  45 +
  46 + ret = modbus_listen(&mb_param, query, &query_size);
  47 + if (ret == 0) {
  48 + manage_query(&mb_param, query, query_size, &mb_mapping);
  49 + } else if (ret == CONNECTION_CLOSED) {
  50 + /* Connection closed by the client, end of server */
  51 + break;
  52 + } else {
  53 + printf("Error in modbus_listen (%d)\n", ret);
  54 + }
  55 + }
  56 +
  57 + close(socket);
  58 + modbus_mapping_free(&mb_mapping);
  59 + modbus_close(&mb_param);
  60 +
  61 + return 0;
  62 +}
  63 +
... ...
tests/wscript
... ... @@ -19,3 +19,17 @@ def build(bld):
19 19 obj.uselib_local = 'modbus'
20 20 obj.target = 'test-master-random'
21 21 obj.inst_var = 0
  22 +
  23 + obj = bld.create_obj('cc', 'program')
  24 + obj.source = 'bench-bandwidth-slave.c'
  25 + obj.includes = '. ..'
  26 + obj.uselib_local = 'modbus'
  27 + obj.target = 'bench-bandwidth-slave'
  28 + obj.inst_var = 0
  29 +
  30 + obj = bld.create_obj('cc', 'program')
  31 + obj.source = 'bench-bandwidth-master.c'
  32 + obj.includes = '. ..'
  33 + obj.uselib_local = 'modbus'
  34 + obj.target = 'bench-bandwidth-master'
  35 + obj.inst_var = 0
... ...