mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
rewrite of histogram class
git-svn-id: https://zerberus.eonerc.rwth-aachen.de:8443/svn/s2ss/trunk@260 8ec27952-4edc-4aab-86aa-e87bb2611832
This commit is contained in:
parent
c8d412df73
commit
8bd93e40fd
9 changed files with 145 additions and 85 deletions
|
@ -1,5 +1,5 @@
|
|||
TARGETS = server send random receive test
|
||||
SRCS = server.c send.c receive.c random.c node.c path.c utils.c socket.c msg.c cfg.c if.c tc.c
|
||||
SRCS = server.c send.c receive.c random.c node.c path.c utils.c socket.c msg.c cfg.c if.c tc.c hist.c
|
||||
|
||||
# Default target: build everything
|
||||
all: $(TARGETS)
|
||||
|
@ -7,11 +7,11 @@ all: $(TARGETS)
|
|||
COMMON = socket.o if.o utils.o msg.o node.o cfg.o tc.o hooks.o
|
||||
|
||||
# Dependencies for individual binaries
|
||||
server: $(COMMON) path.o
|
||||
server: $(COMMON) path.o hist.o
|
||||
send: $(COMMON)
|
||||
receive: $(COMMON)
|
||||
random: utils.o msg.o
|
||||
test: $(COMMON)
|
||||
test: $(COMMON) hist.o
|
||||
|
||||
VPATH = src
|
||||
|
||||
|
|
|
@ -20,10 +20,6 @@
|
|||
/** Socket priority */
|
||||
#define SOCKET_PRIO 7
|
||||
|
||||
/* Some parameters for histogram statistics */
|
||||
#define HIST_HEIGHT 50
|
||||
#define HIST_SEQ 17
|
||||
|
||||
/* Protocol numbers */
|
||||
#define IPPROTO_S2SS 137
|
||||
#define ETH_P_S2SS 0xBABE
|
||||
|
|
36
server/include/hist.h
Normal file
36
server/include/hist.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/** Histogram functions.
|
||||
*
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014, Institute for Automation of Complex Power Systems, EONERC
|
||||
*/
|
||||
|
||||
#ifndef _HIST_H_
|
||||
#define _HIST_H_
|
||||
|
||||
#define HIST_HEIGHT 50
|
||||
#define HIST_SEQ 17
|
||||
|
||||
/** Histogram structure */
|
||||
struct hist {
|
||||
double start;
|
||||
double end;
|
||||
double resolution;
|
||||
int length;
|
||||
unsigned *data;
|
||||
};
|
||||
|
||||
void hist_init(struct hist *h, double start, double end, double resolution);
|
||||
|
||||
void hist_free(struct hist *h);
|
||||
|
||||
void hist_reset(struct hist *h);
|
||||
|
||||
void hist_put(struct hist *h, double value);
|
||||
|
||||
/** Print ASCII style plot of histogram */
|
||||
void hist_plot(struct hist *h);
|
||||
|
||||
/** Dump histogram data in Matlab format */
|
||||
void hist_dump(struct hist *h);
|
||||
|
||||
#endif /* _HIST_H_ */
|
|
@ -12,6 +12,7 @@
|
|||
#include <libconfig.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "hist.h"
|
||||
#include "node.h"
|
||||
#include "msg.h"
|
||||
#include "hooks.h"
|
||||
|
@ -35,6 +36,9 @@ struct path
|
|||
|
||||
/** A pointer to the last received message */
|
||||
struct msg *last;
|
||||
|
||||
/** Counter for received messages according to their sequence no displacement */
|
||||
struct hist histogram;
|
||||
|
||||
/** Last known message number */
|
||||
unsigned int sequence;
|
||||
|
@ -49,8 +53,6 @@ struct path
|
|||
unsigned int skipped;
|
||||
/** Counter for dropped messages due to reordering */
|
||||
unsigned int dropped;
|
||||
/** Counter for received messages according to their sequence no displacement */
|
||||
unsigned int histogram[HIST_SEQ];
|
||||
|
||||
/** The thread id for this path */
|
||||
pthread_t recv_tid;
|
||||
|
|
|
@ -81,12 +81,6 @@ double timespec_delta(struct timespec *start, struct timespec *end);
|
|||
/** Get period as timespec from rate */
|
||||
struct timespec timespec_rate(double rate);
|
||||
|
||||
/** Print ASCII style plot of histogram */
|
||||
void hist_plot(unsigned *hist, int length);
|
||||
|
||||
/** Dump histogram data in Matlab format */
|
||||
void hist_dump(unsigned *hist, int length);
|
||||
|
||||
/** A system(2) emulator with popen/pclose(2) and proper output handling */
|
||||
int system2(const char* cmd, ...);
|
||||
|
||||
|
|
85
server/src/hist.c
Normal file
85
server/src/hist.c
Normal file
|
@ -0,0 +1,85 @@
|
|||
/** Histogram functions.
|
||||
*
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 2014, Institute for Automation of Complex Power Systems, EONERC
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "hist.h"
|
||||
|
||||
void hist_init(struct hist *h, double start, double end, double resolution)
|
||||
{
|
||||
h->start = start;
|
||||
h->end = end;
|
||||
h->resolution = resolution;
|
||||
h->length = (end - start) / resolution;
|
||||
h->data = malloc(h->length * sizeof(unsigned));
|
||||
|
||||
hist_reset(h);
|
||||
}
|
||||
|
||||
void hist_free(struct hist *h)
|
||||
{
|
||||
free(h->data);
|
||||
}
|
||||
|
||||
void hist_put(struct hist *h, double value)
|
||||
{
|
||||
int index = round((value - h->start) / h->resolution);
|
||||
|
||||
if (index >= 0 && index < h->length)
|
||||
h->data[index]++;
|
||||
}
|
||||
|
||||
void hist_reset(struct hist *h)
|
||||
{
|
||||
memset(h->data, 0, h->length * sizeof(unsigned));
|
||||
}
|
||||
|
||||
void hist_plot(struct hist *h)
|
||||
{
|
||||
unsigned min = UINT_MAX;
|
||||
unsigned max = 0;
|
||||
|
||||
/* Get max, first & last */
|
||||
for (int i = 0; i < h->length; i++) {
|
||||
if (h->data[i] > max)
|
||||
max = h->data[i];
|
||||
if (h->data[i] < min)
|
||||
min = h->data[i];
|
||||
}
|
||||
|
||||
char buf[HIST_HEIGHT];
|
||||
memset(buf, '#', HIST_HEIGHT);
|
||||
|
||||
/* Print plot */
|
||||
info("%5s | %5s | %s", "Value", "Occur", "Histogram Plot:");
|
||||
for (int i = 0; i < h->length; i++) {
|
||||
double val = h->start + i * h->resolution;
|
||||
int bar = HIST_HEIGHT * ((double) h->data[i] / max);
|
||||
|
||||
if (h->data[i] == min) info("%5.2e | " GRN("%5u") " | %.*s", val, h->data[i], bar, buf);
|
||||
else if (h->data[i] == max) info("%5.2e | " RED("%5u") " | %.*s", val, h->data[i], bar, buf);
|
||||
else info("%5.2e | " "%5u" " | %.*s", val, h->data[i], bar, buf);
|
||||
}
|
||||
}
|
||||
|
||||
void hist_dump(struct hist *h)
|
||||
{
|
||||
char tok[8];
|
||||
char buf[h->length * sizeof(tok)];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
/* Print in Matlab vector format */
|
||||
for (int i = 0; i < h->length; i++) {
|
||||
snprintf(tok, sizeof(tok), "%u ", h->data[i]);
|
||||
strncat(buf, tok, sizeof(buf) - strlen(buf));
|
||||
}
|
||||
|
||||
info("hist = [ %s]", buf);
|
||||
}
|
|
@ -93,9 +93,7 @@ static void * path_run(void *arg)
|
|||
if (dist > UINT16_MAX / 2)
|
||||
dist -= UINT16_MAX;
|
||||
|
||||
int idx = HIST_SEQ / 2 + dist;
|
||||
if (idx < HIST_SEQ && idx >= 0)
|
||||
p->histogram[idx]++;
|
||||
hist_put(&p->histogram, dist);
|
||||
|
||||
/* Handle simulation restart */
|
||||
if (m->sequence == 0 && abs(dist) > 16) {
|
||||
|
@ -112,8 +110,7 @@ static void * path_run(void *arg)
|
|||
p->skipped = 0;
|
||||
p->dropped = 0;
|
||||
|
||||
/* Reset sequence no tracking */
|
||||
memset(p->histogram, 0, sizeof(p->histogram));
|
||||
hist_reset(&p->histogram);
|
||||
}
|
||||
else if (dist <= 0 && p->received > 1) {
|
||||
p->dropped++;
|
||||
|
@ -146,6 +143,8 @@ int path_start(struct path *p)
|
|||
{ INDENT
|
||||
info("Starting path: %12s " GRN("=>") " %-12s", p->in->name, p->out->name);
|
||||
|
||||
hist_init(&p->histogram, -HIST_SEQ, +HIST_SEQ, 1);
|
||||
|
||||
/* At fixed rate mode, we start another thread for sending */
|
||||
if (p->rate)
|
||||
pthread_create(&p->sent_tid, NULL, &path_send, (void *) p);
|
||||
|
@ -165,11 +164,10 @@ int path_stop(struct path *p)
|
|||
pthread_join(p->sent_tid, NULL);
|
||||
}
|
||||
|
||||
if (p->received) {
|
||||
path_stats(p);
|
||||
hist_plot(p->histogram, HIST_SEQ);
|
||||
hist_dump(p->histogram, HIST_SEQ);
|
||||
}
|
||||
path_stats(p);
|
||||
hist_plot(&p->histogram);
|
||||
hist_dump(&p->histogram);
|
||||
hist_free(&p->histogram);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "msg.h"
|
||||
#include "node.h"
|
||||
#include "utils.h"
|
||||
#include "hist.h"
|
||||
|
||||
static struct settings set;
|
||||
static struct node *node;
|
||||
|
@ -28,11 +29,6 @@ int running = 1;
|
|||
|
||||
#define CLOCK_ID CLOCK_MONOTONIC_RAW
|
||||
|
||||
#define RTT_MIN 20
|
||||
#define RTT_MAX 100
|
||||
#define RTT_RESOLUTION 2
|
||||
#define RTT_HIST (int) ((RTT_MAX - RTT_MIN) / RTT_RESOLUTION)
|
||||
|
||||
void quit(int sig, siginfo_t *si, void *ptr)
|
||||
{
|
||||
running = 0;
|
||||
|
@ -82,11 +78,9 @@ int main(int argc, char *argv[])
|
|||
double rtt_max = LLONG_MIN;
|
||||
double rtt_min = LLONG_MAX;
|
||||
double avg = 0;
|
||||
int bar;
|
||||
unsigned hist[RTT_HIST];
|
||||
|
||||
|
||||
memset(hist, 0, RTT_HIST * sizeof(unsigned));
|
||||
|
||||
struct hist histogram;
|
||||
hist_init(&histogram, 0, 2e-4, 1e-5);
|
||||
|
||||
#if 1 /* Print header */
|
||||
fprintf(stdout, "%17s", "timestamp");
|
||||
|
@ -106,11 +100,8 @@ int main(int argc, char *argv[])
|
|||
if (rtt < rtt_min) rtt_min = rtt;
|
||||
|
||||
avg += rtt;
|
||||
|
||||
/* Update histogram */
|
||||
bar = (rtt * 1000 / RTT_RESOLUTION) - (RTT_MIN / RTT_RESOLUTION);
|
||||
if (bar < RTT_HIST)
|
||||
hist[bar]++;
|
||||
|
||||
hist_put(&histogram, rtt);
|
||||
|
||||
#if 1
|
||||
struct timespec ts;
|
||||
|
@ -125,8 +116,9 @@ int main(int argc, char *argv[])
|
|||
|
||||
free(ts2);
|
||||
|
||||
hist_plot(hist, RTT_HIST);
|
||||
hist_dump(hist, RTT_HIST);
|
||||
hist_plot(&histogram);
|
||||
hist_dump(&histogram);
|
||||
hist_free(&histogram);
|
||||
}
|
||||
|
||||
node_stop(node);
|
||||
|
|
|
@ -103,49 +103,6 @@ struct timespec timespec_rate(double rate)
|
|||
return ts;
|
||||
}
|
||||
|
||||
void hist_plot(unsigned *hist, int length)
|
||||
{
|
||||
char buf[HIST_HEIGHT + 32];
|
||||
int bar;
|
||||
int max = 0;
|
||||
|
||||
/* Get max, first & last */
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (hist[i] > hist[max])
|
||||
max = i;
|
||||
}
|
||||
|
||||
/* Print header */
|
||||
info("%2s | %5s | %s", "Id", "Value", "Histogram Plot:");
|
||||
|
||||
/* Print plot */
|
||||
memset(buf, '#', sizeof(buf));
|
||||
for (int i = 0; i < length; i++) {
|
||||
bar = HIST_HEIGHT * (float) hist[i] / hist[max];
|
||||
if (hist[i] == 0)
|
||||
info("%2u | " GRN("%5u") " | " , i, hist[i]);
|
||||
else if (hist[i] == hist[max])
|
||||
info("%2u | " RED("%5u") " | " BLD("%.*s"), i, hist[i], bar, buf);
|
||||
else
|
||||
info("%2u | " "%5u" " | " "%.*s", i, hist[i], bar, buf);
|
||||
}
|
||||
}
|
||||
|
||||
void hist_dump(unsigned *hist, int length)
|
||||
{
|
||||
char tok[16];
|
||||
char buf[length * sizeof(tok)];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
/* Print in Matlab vector format */
|
||||
for (int i = 0; i < length; i++) {
|
||||
snprintf(tok, sizeof(tok), "%u ", hist[i]);
|
||||
strncat(buf, tok, sizeof(buf)-strlen(buf));
|
||||
}
|
||||
|
||||
info("Matlab: hist = [ %s]", buf);
|
||||
}
|
||||
|
||||
/** @todo: Proper way: create additional pipe for stderr in child process */
|
||||
int system2(const char *cmd, ...)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue