MINOR: activity: declare a new structure to collect per-function activity

The new sched_activity structure will be used to collect task-level
activity based on the target function. The principle is to declare a
large enough array to make collisions rare (256 entries), and hash
the function pointer using a reduced XXH to decide where to store the
stats. On first computation an entry is definitely assigned to the
array and it's done atomically. A special entry (0) is used to store
collisions ("others"). The goal is to make it easy and inexpensive for
the scheduler code to use these to store #calls, cpu_time and lat_time
for each task.
This commit is contained in:
Willy Tarreau 2021-01-28 19:19:26 +01:00
parent aa622b822b
commit 3fb6a7b46e
3 changed files with 42 additions and 0 deletions

View File

@ -74,6 +74,19 @@ struct activity {
char __end[0] __attribute__((aligned(64))); // align size to 64.
};
/* global profiling stats from the scheduler: each entry corresponds to a
* task or tasklet ->process function pointer, with a number of calls and
* a total time. Each entry is unique, except entry 0 which is for colliding
* hashes (i.e. others). All of these must be accessed atomically.
*/
struct sched_activity {
const void *func;
uint64_t calls;
uint64_t cpu_time;
uint64_t lat_time;
};
#endif /* _HAPROXY_ACTIVITY_T_H */
/*

View File

@ -22,6 +22,7 @@
#ifndef _HAPROXY_ACTIVITY_H
#define _HAPROXY_ACTIVITY_H
#include <import/xxhash.h>
#include <haproxy/activity-t.h>
#include <haproxy/api.h>
#include <haproxy/freq_ctr.h>
@ -30,6 +31,7 @@
extern unsigned int profiling;
extern unsigned long task_profiling_mask;
extern struct activity activity[MAX_THREADS];
extern struct sched_activity sched_activity[256];
void report_stolen_time(uint64_t stolen);
@ -88,6 +90,31 @@ static inline void activity_count_runtime()
}
}
/* Computes the index of function pointer <func> for use with sched_activity[]
* or any other similar array passed in <array>, and returns a pointer to the
* entry after having atomically assigned it to this function pointer. Note
* that in case of collision, the first entry is returned instead ("other").
*/
static inline struct sched_activity *sched_activity_entry(struct sched_activity *array, const void *func)
{
uint64_t hash = XXH64_avalanche(XXH64_mergeRound((size_t)func, (size_t)func));
struct sched_activity *ret;
const void *old = NULL;
hash ^= (hash >> 32);
hash ^= (hash >> 16);
hash ^= (hash >> 8);
hash &= 0xff;
ret = &array[hash];
if (likely(ret->func == func))
return ret;
if (HA_ATOMIC_CAS(&ret->func, &old, func))
return ret;
return array;
}
#endif /* _HAPROXY_ACTIVITY_H */

View File

@ -27,6 +27,8 @@ unsigned long task_profiling_mask = 0;
/* One struct per thread containing all collected measurements */
struct activity activity[MAX_THREADS] __attribute__((aligned(64))) = { };
/* One struct per function pointer hash entry (256 values, 0=collision) */
struct sched_activity sched_activity[256] __attribute__((aligned(64))) = { };
/* Updates the current thread's statistics about stolen CPU time. The unit for
* <stolen> is half-milliseconds.