REORG: time/activity: move activity measurements to activity.{c,h}

At the moment the situation with activity measurement is quite tricky
because the struct activity is defined in global.h and declared in
haproxy.c, with operations made in time.h and relying on freq_ctr
which are defined in freq_ctr.h which itself includes time.h. It's
barely possible to touch any of these files without breaking all the
circular dependency.

Let's move all this stuff to activity.{c,h} and be done with it. The
measurement of active and stolen time is now done in a dedicated
function called just after tv_before_poll() instead of mixing the two,
which used to be a lazy (but convenient) decision.

No code was changed, stuff was just moved around.
This commit is contained in:
Willy Tarreau 2018-11-22 08:31:09 +01:00
parent 17306b905e
commit 609aad9e73
15 changed files with 176 additions and 72 deletions

View File

@ -943,7 +943,7 @@ OBJS = src/proto_http.o src/cfgparse-listen.o src/proto_htx.o src/stream.o \
src/http.o src/hpack-dec.o src/action.o src/proto_udp.o src/http_acl.o \
src/xxhash.o src/hpack-enc.o src/h2.o src/freq_ctr.o src/lru.o \
src/protocol.o src/arg.o src/hpack-huff.o src/hdr_idx.o src/base64.o \
src/hash.o src/mailers.o
src/hash.o src/mailers.o src/activity.o
EBTREE_OBJS = $(EBTREE_DIR)/ebtree.o $(EBTREE_DIR)/eb32sctree.o \
$(EBTREE_DIR)/eb32tree.o $(EBTREE_DIR)/eb64tree.o \

View File

@ -85,11 +85,6 @@ REGPRM2 int tv_ms_cmp(const struct timeval *tv1, const struct timeval *tv2);
*/
REGPRM2 int tv_ms_cmp2(const struct timeval *tv1, const struct timeval *tv2);
/* Updates the current thread's statistics about stolen CPU time. The unit for
* <stolen> is half-milliseconds.
*/
REGPRM1 void report_stolen_time(uint64_t stolen);
/**** general purpose functions and macros *******************************/
@ -581,26 +576,6 @@ static inline void measure_idle()
*/
static inline void tv_entering_poll()
{
uint64_t new_mono_time;
uint64_t new_cpu_time;
int64_t stolen;
new_cpu_time = now_cpu_time();
new_mono_time = now_mono_time();
if (prev_cpu_time && prev_mono_time) {
new_cpu_time -= prev_cpu_time;
new_mono_time -= prev_mono_time;
stolen = new_mono_time - new_cpu_time;
if (stolen >= 500000) {
stolen /= 500000;
/* more than half a millisecond difference might
* indicate an undesired preemption.
*/
report_stolen_time(stolen);
}
}
gettimeofday(&before_poll, NULL);
}

69
include/proto/activity.h Normal file
View File

@ -0,0 +1,69 @@
/*
* include/proto/activity.h
* This file contains macros and inline functions for activity measurements.
*
* Copyright (C) 2000-2018 Willy Tarreau - w@1wt.eu
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, version 2.1
* exclusively.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _PROTO_ACTIVITY_H
#define _PROTO_ACTIVITY_H
#include <common/config.h>
#include <common/hathreads.h>
#include <common/time.h>
#include <types/activity.h>
extern struct activity activity[MAX_THREADS];
void report_stolen_time(uint64_t stolen);
/* Collect date and time information before calling poll(). This will be used
* to count the run time of the past loop and the sleep time of the next poll.
*/
static inline void activity_count_runtime()
{
uint64_t new_mono_time;
uint64_t new_cpu_time;
int64_t stolen;
new_cpu_time = now_cpu_time();
new_mono_time = now_mono_time();
if (prev_cpu_time && prev_mono_time) {
new_cpu_time -= prev_cpu_time;
new_mono_time -= prev_mono_time;
stolen = new_mono_time - new_cpu_time;
if (unlikely(stolen >= 500000)) {
stolen /= 500000;
/* more than half a millisecond difference might
* indicate an undesired preemption.
*/
report_stolen_time(stolen);
}
}
}
#endif /* _PROTO_ACTIVITY_H */
/*
* Local variables:
* c-indent-level: 8
* c-basic-offset: 8
* End:
*/

View File

@ -30,9 +30,8 @@
#include <common/config.h>
#include <common/ticks.h>
#include <common/time.h>
#include <types/fd.h>
#include <types/global.h>
#include <proto/activity.h>
/* public variables */

63
include/types/activity.h Normal file
View File

@ -0,0 +1,63 @@
/*
* include/types/activity.h
* This file contains structure declarations for activity measurements.
*
* Copyright (C) 2000-2018 Willy Tarreau - w@1wt.eu
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, version 2.1
* exclusively.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _TYPES_ACTIVITY_H
#define _TYPES_ACTIVITY_H
#include <common/config.h>
#include <types/freq_ctr.h>
/* per-thread activity reports. It's important that it's aligned on cache lines
* because some elements will be updated very often. Most counters are OK on
* 32-bit since this will be used during debugging sessions for troubleshooting
* in iterative mode.
*/
struct activity {
unsigned int loops; // complete loops in run_poll_loop()
unsigned int wake_cache; // active fd_cache prevented poll() from sleeping
unsigned int wake_tasks; // active tasks prevented poll() from sleeping
unsigned int wake_signal; // pending signal prevented poll() from sleeping
unsigned int poll_exp; // number of times poll() sees an expired timeout (includes wake_*)
unsigned int poll_drop; // poller dropped a dead FD from the update list
unsigned int poll_dead; // poller woke up with a dead FD
unsigned int poll_skip; // poller skipped another thread's FD
unsigned int fd_skip; // fd cache skipped another thread's FD
unsigned int fd_lock; // fd cache skipped a locked FD
unsigned int fd_del; // fd cache detected a deleted FD
unsigned int conn_dead; // conn_fd_handler woke up on an FD indicating a dead connection
unsigned int stream; // calls to process_stream()
unsigned int empty_rq; // calls to process_runnable_tasks() with nothing for the thread
unsigned int long_rq; // process_runnable_tasks() left with tasks in the run queue
unsigned int cpust_total; // sum of half-ms stolen per thread
struct freq_ctr cpust_1s; // avg amount of half-ms stolen over last second
struct freq_ctr_period cpust_15s; // avg amount of half-ms stolen over last 15s
char __pad[0]; // unused except to check remaining room
char __end[0] __attribute__((aligned(64))); // align size to 64.
};
#endif /* _TYPES_ACTIVITY_H */
/*
* Local variables:
* c-indent-level: 8
* c-basic-offset: 8
* End:
*/

View File

@ -28,7 +28,6 @@
#include <common/standard.h>
#include <common/hathreads.h>
#include <types/freq_ctr.h>
#include <types/listener.h>
#include <types/proxy.h>
#include <types/task.h>
@ -177,34 +176,6 @@ struct global {
#endif
};
/* per-thread activity reports. It's important that it's aligned on cache lines
* because some elements will be updated very often. Most counters are OK on
* 32-bit since this will be used during debugging sessions for troubleshooting
* in iterative mode.
*/
struct activity {
unsigned int loops; // complete loops in run_poll_loop()
unsigned int wake_cache; // active fd_cache prevented poll() from sleeping
unsigned int wake_tasks; // active tasks prevented poll() from sleeping
unsigned int wake_signal; // pending signal prevented poll() from sleeping
unsigned int poll_exp; // number of times poll() sees an expired timeout (includes wake_*)
unsigned int poll_drop; // poller dropped a dead FD from the update list
unsigned int poll_dead; // poller woke up with a dead FD
unsigned int poll_skip; // poller skipped another thread's FD
unsigned int fd_skip; // fd cache skipped another thread's FD
unsigned int fd_lock; // fd cache skipped a locked FD
unsigned int fd_del; // fd cache detected a deleted FD
unsigned int conn_dead; // conn_fd_handler woke up on an FD indicating a dead connection
unsigned int stream; // calls to process_stream()
unsigned int empty_rq; // calls to process_runnable_tasks() with nothing for the thread
unsigned int long_rq; // process_runnable_tasks() left with tasks in the run queue
unsigned int cpust_total; // sum of half-ms stolen per thread
struct freq_ctr cpust_1s; // avg amount of half-ms stolen over last second
struct freq_ctr_period cpust_15s; // avg amount of half-ms stolen over last 15s
char __pad[0]; // unused except to check remaining room
char __end[0] __attribute__((aligned(64))); // align size to 64.
};
/*
* Structure used to describe the processes in master worker mode
*/
@ -221,7 +192,6 @@ struct mworker_proc {
};
extern struct global global;
extern struct activity activity[MAX_THREADS];
extern int pid; /* current process id */
extern int relative_pid; /* process id starting at 1 */
extern unsigned long pid_bit; /* bit corresponding to the process id */

31
src/activity.c Normal file
View File

@ -0,0 +1,31 @@
/*
* activity measurement functions.
*
* Copyright 2000-2018 Willy Tarreau <w@1wt.eu>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
*/
#include <common/config.h>
#include <common/standard.h>
#include <common/hathreads.h>
#include <types/activity.h>
#include <proto/freq_ctr.h>
/* One struct per thread containing all collected measurements */
struct activity activity[MAX_THREADS] __attribute__((aligned(64))) = { };
/* Updates the current thread's statistics about stolen CPU time. The unit for
* <stolen> is half-milliseconds.
*/
void report_stolen_time(uint64_t stolen)
{
activity[tid].cpust_total += stolen;
update_freq_ctr(&activity[tid].cpust_1s, stolen);
update_freq_ctr_period(&activity[tid].cpust_15s, 15000, stolen);
}

View File

@ -45,6 +45,7 @@
#include <types/dns.h>
#include <types/stats.h>
#include <proto/activity.h>
#include <proto/backend.h>
#include <proto/channel.h>
#include <proto/checks.h>

View File

@ -25,6 +25,7 @@
#include <types/global.h>
#include <proto/activity.h>
#include <proto/fd.h>
@ -147,6 +148,7 @@ REGPRM2 static void _do_poll(struct poller *p, int exp)
/* now let's wait for polled events */
wait_time = compute_poll_timeout(exp);
tv_entering_poll();
activity_count_runtime();
status = epoll_wait(epoll_fd[tid], epoll_events, global.tune.maxpollevents, wait_time);
tv_leaving_poll(wait_time, status);

View File

@ -26,6 +26,7 @@
#include <types/global.h>
#include <proto/activity.h>
#include <proto/fd.h>
@ -135,6 +136,7 @@ REGPRM2 static void _do_poll(struct poller *p, int exp)
timeout.tv_nsec = (delta_ms % 1000) * 1000000;
fd = global.tune.maxpollevents;
tv_entering_poll();
activity_count_runtime();
status = kevent(kqueue_fd[tid], // int kq
NULL, // const struct kevent *changelist
0, // int nchanges

View File

@ -25,6 +25,7 @@
#include <types/global.h>
#include <proto/activity.h>
#include <proto/fd.h>
@ -195,6 +196,7 @@ REGPRM2 static void _do_poll(struct poller *p, int exp)
/* now let's wait for events */
wait_time = compute_poll_timeout(exp);
tv_entering_poll();
activity_count_runtime();
status = poll(poll_events, nbfd, wait_time);
tv_leaving_poll(wait_time, status);

View File

@ -22,6 +22,7 @@
#include <types/global.h>
#include <proto/activity.h>
#include <proto/fd.h>
@ -165,6 +166,7 @@ REGPRM2 static void _do_poll(struct poller *p, int exp)
delta.tv_sec = (delta_ms / 1000);
delta.tv_usec = (delta_ms % 1000) * 1000;
tv_entering_poll();
activity_count_runtime();
status = select(maxfd,
readnotnull ? tmp_evts[DIR_RD] : NULL,
writenotnull ? tmp_evts[DIR_WR] : NULL,

View File

@ -93,6 +93,7 @@
#include <types/peers.h>
#include <proto/acl.h>
#include <proto/activity.h>
#include <proto/arg.h>
#include <proto/auth.h>
#include <proto/backend.h>
@ -170,8 +171,6 @@ struct global global = {
/* others NULL OK */
};
struct activity activity[MAX_THREADS] __attribute__((aligned(64))) = { };
/*********************************************************************/
int stopping; /* non zero means stopping in progress */

View File

@ -30,6 +30,7 @@
#include <proto/acl.h>
#include <proto/action.h>
#include <proto/activity.h>
#include <proto/arg.h>
#include <proto/backend.h>
#include <proto/channel.h>

View File

@ -18,8 +18,6 @@
#include <common/standard.h>
#include <common/time.h>
#include <common/hathreads.h>
#include <types/global.h>
#include <proto/freq_ctr.h>
THREAD_LOCAL unsigned int ms_left_scaled; /* milliseconds left for current second (0..2^32-1) */
THREAD_LOCAL unsigned int now_ms; /* internal date in milliseconds (may wrap) */
@ -264,16 +262,6 @@ REGPRM2 void tv_update_date(int max_wait, int interrupted)
return;
}
/* Updates the current thread's statistics about stolen CPU time. The unit for
* <stolen> is half-milliseconds.
*/
REGPRM1 void report_stolen_time(uint64_t stolen)
{
activity[tid].cpust_total += stolen;
update_freq_ctr(&activity[tid].cpust_1s, stolen);
update_freq_ctr_period(&activity[tid].cpust_15s, 15000, stolen);
}
/*
* Local variables:
* c-indent-level: 8