forked from Archive/PX4-Autopilot
add interrupt latency printout command and mean/variance to interval performance counter
This commit is contained in:
parent
92eb637d00
commit
9292c8f405
|
@ -254,8 +254,10 @@ static uint16_t latency_actual;
|
||||||
|
|
||||||
/* latency histogram */
|
/* latency histogram */
|
||||||
#define LATENCY_BUCKET_COUNT 8
|
#define LATENCY_BUCKET_COUNT 8
|
||||||
static const uint16_t latency_buckets[LATENCY_BUCKET_COUNT] = { 1, 2, 5, 10, 20, 50, 100, 1000 };
|
__EXPORT const uint16_t latency_bucket_count = LATENCY_BUCKET_COUNT;
|
||||||
static uint32_t latency_counters[LATENCY_BUCKET_COUNT + 1];
|
__EXPORT const uint16_t latency_buckets[LATENCY_BUCKET_COUNT] = { 1, 2, 5, 10, 20, 50, 100, 1000 };
|
||||||
|
__EXPORT uint32_t latency_counters[LATENCY_BUCKET_COUNT + 1];
|
||||||
|
|
||||||
|
|
||||||
/* timer-specific functions */
|
/* timer-specific functions */
|
||||||
static void hrt_tim_init(void);
|
static void hrt_tim_init(void);
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#include <drivers/drv_hrt.h>
|
#include <drivers/drv_hrt.h>
|
||||||
|
#include <math.h>
|
||||||
#include "perf_counter.h"
|
#include "perf_counter.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -84,7 +84,8 @@ struct perf_ctr_interval {
|
||||||
uint64_t time_last;
|
uint64_t time_last;
|
||||||
uint64_t time_least;
|
uint64_t time_least;
|
||||||
uint64_t time_most;
|
uint64_t time_most;
|
||||||
|
float mean;
|
||||||
|
float M2;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -109,6 +110,7 @@ perf_alloc(enum perf_counter_type type, const char *name)
|
||||||
|
|
||||||
case PC_INTERVAL:
|
case PC_INTERVAL:
|
||||||
ctr = (perf_counter_t)calloc(sizeof(struct perf_ctr_interval), 1);
|
ctr = (perf_counter_t)calloc(sizeof(struct perf_ctr_interval), 1);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -156,6 +158,8 @@ perf_count(perf_counter_t handle)
|
||||||
case 1:
|
case 1:
|
||||||
pci->time_least = now - pci->time_last;
|
pci->time_least = now - pci->time_last;
|
||||||
pci->time_most = now - pci->time_last;
|
pci->time_most = now - pci->time_last;
|
||||||
|
pci->mean = pci->time_least / 1e6f;
|
||||||
|
pci->M2 = 0;
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
hrt_abstime interval = now - pci->time_last;
|
hrt_abstime interval = now - pci->time_last;
|
||||||
|
@ -163,6 +167,12 @@ perf_count(perf_counter_t handle)
|
||||||
pci->time_least = interval;
|
pci->time_least = interval;
|
||||||
if (interval > pci->time_most)
|
if (interval > pci->time_most)
|
||||||
pci->time_most = interval;
|
pci->time_most = interval;
|
||||||
|
// maintain mean and variance of interval in seconds
|
||||||
|
// Knuth/Welford recursive mean and variance of update intervals (via Wikipedia)
|
||||||
|
float dt = interval / 1e6f;
|
||||||
|
float delta_intvl = dt - pci->mean;
|
||||||
|
pci->mean += delta_intvl / pci->event_count;
|
||||||
|
pci->M2 += delta_intvl * (dt - pci->mean);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -313,13 +323,16 @@ perf_print_counter_fd(int fd, perf_counter_t handle)
|
||||||
|
|
||||||
case PC_INTERVAL: {
|
case PC_INTERVAL: {
|
||||||
struct perf_ctr_interval *pci = (struct perf_ctr_interval *)handle;
|
struct perf_ctr_interval *pci = (struct perf_ctr_interval *)handle;
|
||||||
|
float rms = sqrtf(pci->M2 / (pci->event_count-1));
|
||||||
|
|
||||||
dprintf(fd, "%s: %llu events, %lluus avg, min %lluus max %lluus\n",
|
dprintf(fd, "%s: %llu events, %lluus avg, min %lluus max %lluus %5.3f msec mean %5.3f msec rms\n",
|
||||||
handle->name,
|
handle->name,
|
||||||
pci->event_count,
|
pci->event_count,
|
||||||
(pci->time_last - pci->time_first) / pci->event_count,
|
(pci->time_last - pci->time_first) / pci->event_count,
|
||||||
pci->time_least,
|
pci->time_least,
|
||||||
pci->time_most);
|
pci->time_most,
|
||||||
|
(double)(1000 * pci->mean),
|
||||||
|
(double)(1000 * rms));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,6 +378,21 @@ perf_print_all(int fd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern const uint16_t latency_bucket_count;
|
||||||
|
extern uint32_t latency_counters[];
|
||||||
|
extern const uint16_t latency_buckets[];
|
||||||
|
|
||||||
|
void
|
||||||
|
perf_print_latency(int fd)
|
||||||
|
{
|
||||||
|
dprintf(fd, "bucket : events\n");
|
||||||
|
for (int i = 0; i < latency_bucket_count; i++) {
|
||||||
|
printf(" %4i : %i\n", latency_buckets[i], latency_counters[i]);
|
||||||
|
}
|
||||||
|
// print the overflow bucket value
|
||||||
|
dprintf(fd, " >%4i : %i\n", latency_buckets[latency_bucket_count-1], latency_counters[latency_bucket_count]);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
perf_reset_all(void)
|
perf_reset_all(void)
|
||||||
{
|
{
|
||||||
|
@ -374,4 +402,7 @@ perf_reset_all(void)
|
||||||
perf_reset(handle);
|
perf_reset(handle);
|
||||||
handle = (perf_counter_t)sq_next(&handle->link);
|
handle = (perf_counter_t)sq_next(&handle->link);
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i <= latency_bucket_count; i++) {
|
||||||
|
latency_counters[i] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ __EXPORT extern void perf_begin(perf_counter_t handle);
|
||||||
* End a performance event.
|
* End a performance event.
|
||||||
*
|
*
|
||||||
* This call applies to counters that operate over ranges of time; PC_ELAPSED etc.
|
* This call applies to counters that operate over ranges of time; PC_ELAPSED etc.
|
||||||
* If a call is made without a corresopnding perf_begin call, or if perf_cancel
|
* If a call is made without a corresponding perf_begin call, or if perf_cancel
|
||||||
* has been called subsequently, no change is made to the counter.
|
* has been called subsequently, no change is made to the counter.
|
||||||
*
|
*
|
||||||
* @param handle The handle returned from perf_alloc.
|
* @param handle The handle returned from perf_alloc.
|
||||||
|
@ -142,6 +142,13 @@ __EXPORT extern void perf_print_counter_fd(int fd, perf_counter_t handle);
|
||||||
*/
|
*/
|
||||||
__EXPORT extern void perf_print_all(int fd);
|
__EXPORT extern void perf_print_all(int fd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print hrt latency counters.
|
||||||
|
*
|
||||||
|
* @param fd File descriptor to print to - e.g. 0 for stdout
|
||||||
|
*/
|
||||||
|
__EXPORT extern void perf_print_latency(int fd);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset all of the performance counters.
|
* Reset all of the performance counters.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -68,8 +68,12 @@ int perf_main(int argc, char *argv[])
|
||||||
if (strcmp(argv[1], "reset") == 0) {
|
if (strcmp(argv[1], "reset") == 0) {
|
||||||
perf_reset_all();
|
perf_reset_all();
|
||||||
return 0;
|
return 0;
|
||||||
|
} else if (strcmp(argv[1], "latency") == 0) {
|
||||||
|
perf_print_latency(0 /* stdout */);
|
||||||
|
fflush(stdout);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
printf("Usage: perf <reset>\n");
|
printf("Usage: perf [reset | latency]\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue