Add infrastructure to compute timed averages
cover Add infrastructure to compute timed averages
This series adds a new module that can be used to compute the average of a set of values in a certain period of time. This will be used by the accounting code to obtain statistics such as the min / max / average latency of I/O commands.
This is based on Benoît's code, originally written last year.
Regards,
Berto
Alberto Garcia (3):
timer: Move NANOSECONDS_PER_SECONDS to timer.h
timer: Use a single definition of NSEC_PER_SEC for the whole codebase
util: Infrastructure for computing recent averages
hw/ppc/ppc.c | 2 - hw/ppc/spapr_rtc.c | 3 +- hw/timer/mc146818rtc.c | 1 - hw/usb/hcd-ehci.c | 2 +- include/qemu/throttle.h | 2 - include/qemu/timed-average.h | 58 ++++++++++++ include/qemu/timer.h | 2 + tests/Makefile | 4 + tests/rtl8139-test.c | 10 +-- tests/test-throttle.c | 8 +- tests/test-timed-average.c | 89 ++++++++++++++++++ tests/wdt_ib700-test.c | 15 ++-- util/Makefile.objs | 1 + util/throttle.c | 4 +- util/timed-average.c | 208 +++++++++++++++++++++++++++++++++++++++++++ 15 files changed, 382 insertions(+), 27 deletions(-) create mode 100644 include/qemu/timed-average.h create mode 100644 tests/test-timed-average.c create mode 100644 util/timed-average.c
Signature · 1 line
2.1.4
PATCH 1/3 timer: Move NANOSECONDS_PER_SECONDS to timer.h
We want to be able to reuse this define by making it common to multiple QEMU modules.
This also makes it an integer since there's no need for it to be a float.
--- include/qemu/throttle.h | 2 -- include/qemu/timer.h | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-)
include/qemu/throttle.h +0 -2
@@ -27,8 +27,6 @@#include "qemu-common.h" #include "qemu/timer.h" -#define NANOSECONDS_PER_SECOND 1000000000.0 - typedef enum { THROTTLE_BPS_TOTAL, THROTTLE_BPS_READ,
include/qemu/timer.h +2 -0
@@ -5,6 +5,8 @@#include "qemu-common.h" #include "qemu/notify.h" +#define NANOSECONDS_PER_SECOND 1000000000LL +/* timers */ #define SCALE_MS 1000000
Signature · 1 line
2.1.4
PATCH 2/3 timer: Use a single definition of NSEC_PER_SEC for the whole codebase
In reply to Alberto Garcia--- hw/ppc/ppc.c | 2 -- hw/ppc/spapr_rtc.c | 3 +-- hw/timer/mc146818rtc.c | 1 - hw/usb/hcd-ehci.c | 2 +- include/qemu/timer.h | 2 +- tests/rtl8139-test.c | 10 +++++----- tests/test-throttle.c | 8 ++++---- tests/wdt_ib700-test.c | 15 +++++++-------- util/throttle.c | 4 ++-- 9 files changed, 21 insertions(+), 26 deletions(-)
hw/ppc/ppc.c +0 -2
@@ -51,8 +51,6 @@# define LOG_TB (...) do { } while (0)#endif -#define NSEC_PER_SEC 1000000000LL -static void cpu_ppc_tb_stop (CPUPPCState *env);static void cpu_ppc_tb_start (CPUPPCState *env);
hw/ppc/spapr_rtc.c +1 -2
@@ -26,6 +26,7 @@* */ #include "cpu.h" +#include "qemu/timer.h" #include "sysemu/sysemu.h" #include "hw/ppc/spapr.h" #include "qapi-event.h"
@@ -40,8 +41,6 @@ struct sPAPRRTCState {int64_t ns_offset; }; -#define NSEC_PER_SEC 1000000000LL -void spapr_rtc_read (DeviceState *dev,struct tm *tm,uint32_t *ns) {sPAPRRTCState *rtc =SPAPR_RTC (dev);
hw/timer/mc146818rtc.c +0 -1
@@ -48,7 +48,6 @@# define DPRINTF_C (format, ...) do { } while (0)#endif -#define NSEC_PER_SEC 1000000000LL#define SEC_PER_MIN 60#define MIN_PER_HOUR 60#define SEC_PER_HOUR 3600
hw/usb/hcd-ehci.c +1 -1
@@ -32,7 +32,7 @@#include "trace.h" #define FRAME_TIMER_FREQ 1000 -#define FRAME_TIMER_NS (1000000000 / FRAME_TIMER_FREQ) +#define FRAME_TIMER_NS (NSEC_PER_SEC / FRAME_TIMER_FREQ)#define UFRAME_TIMER_NS (FRAME_TIMER_NS / 8)#define NB_MAXINTRATE 8 // Max rate at which controller issues ints
include/qemu/timer.h +1 -1
@@ -5,7 +5,7 @@#include "qemu-common.h" #include "qemu/notify.h" -#define NANOSECONDS_PER_SECOND 1000000000LL +#define NSEC_PER_SEC 1000000000LL/* timers */
tests/rtl8139-test.c +5 -5
@@ -12,6 +12,7 @@#include "libqtest.h" #include "libqos/pci-pc.h" #include "qemu/osdep.h" +#include "qemu/timer.h" #include "qemu-common.h" /* Tests only initialization so far. TODO: Replace with functional tests */
@@ -20,7 +21,6 @@ static void nop(void) }#define CLK 33000000 -#define NS_PER_SEC 1000000000ULLstatic QPCIBus *pcibus;static QPCIDevice *dev;
@@ -86,7 +86,7 @@ static void test_timer(void)fatal ("time too big %u\n" , curr); }for (cnt =0 ; ; ) { -clock_step (1 *NS_PER_SEC ); +clock_step (1 *NSEC_PER_SEC ); prev = curr; curr =in_Timer ();
@@ -125,7 +125,7 @@ static void test_timer(void)out_IntrStatus (0x4000 ); curr =in_Timer ();out_TimerInt (curr +0.5 *CLK ); -clock_step (1 *NS_PER_SEC ); +clock_step (1 *NSEC_PER_SEC );out_Timer (0 );if ((in_IntrStatus () &0x4000 ) ==0 ) {fatal ("we should have an interrupt here!\n" );
@@ -137,7 +137,7 @@ static void test_timer(void)out_IntrStatus (0x4000 ); curr =in_Timer ();out_TimerInt (curr +0.5 *CLK ); -clock_step (1 *NS_PER_SEC ); +clock_step (1 *NSEC_PER_SEC );out_TimerInt (0 );if ((in_IntrStatus () &0x4000 ) ==0 ) {fatal ("we should have an interrupt here!\n" );
@@ -148,7 +148,7 @@ static void test_timer(void) next = curr +5.0 *CLK ;out_TimerInt (next);for (cnt =0 ; ; ) { -clock_step (1 *NS_PER_SEC ); +clock_step (1 *NSEC_PER_SEC ); prev = curr; curr =in_Timer (); diff = (curr-prev) &0xffffffffu ;
tests/test-throttle.c +4 -4
@@ -36,19 +36,19 @@ static void test_leak_bucket(void) bkt.level =1.5 ;/* leak an op work of time */ -throttle_leak_bucket (&bkt,NANOSECONDS_PER_SECOND /150 ); +throttle_leak_bucket (&bkt,NSEC_PER_SEC /150 );g_assert (bkt.avg ==150 );g_assert (bkt.max ==15 );g_assert (double_cmp (bkt.level,0.5 ));/* leak again emptying the bucket */ -throttle_leak_bucket (&bkt,NANOSECONDS_PER_SECOND /150 ); +throttle_leak_bucket (&bkt,NSEC_PER_SEC /150 );g_assert (bkt.avg ==150 );g_assert (bkt.max ==15 );g_assert (double_cmp (bkt.level,0 ));/* check that the bucket level won't go lower */ -throttle_leak_bucket (&bkt,NANOSECONDS_PER_SECOND /150 ); +throttle_leak_bucket (&bkt,NSEC_PER_SEC /150 );g_assert (bkt.avg ==150 );g_assert (bkt.max ==15 );g_assert (double_cmp (bkt.level,0 ));
@@ -86,7 +86,7 @@ static void test_compute_wait(void) bkt.level =15.5 ; wait =throttle_compute_wait (&bkt);/* time required to do half an operation */ - result = (int64_t )NANOSECONDS_PER_SECOND /150 /2 ; + result = (int64_t )NSEC_PER_SEC /150 /2 ;g_assert (wait == result); }
tests/wdt_ib700-test.c +7 -8
@@ -11,8 +11,7 @@#include <string.h> #include "libqtest.h" #include "qemu/osdep.h" - -#define NS_PER_SEC 1000000000ULL +#include "qemu/timer.h" static void qmp_check_no_event (void ) {
@@ -41,29 +40,29 @@ static QDict *qmp_get_event(const char *name)static QDict *ib700_program_and_wait (QTestState *s) { -clock_step (NS_PER_SEC *40 ); +clock_step (NSEC_PER_SEC *40 );qmp_check_no_event ();/* 2 second limit */ outb (0x443 ,14 );/* Ping */ -clock_step (NS_PER_SEC ); +clock_step (NSEC_PER_SEC );qmp_check_no_event ();outb (0x443 ,14 );/* Disable */ -clock_step (NS_PER_SEC ); +clock_step (NSEC_PER_SEC );qmp_check_no_event ();outb (0x441 ,1 ); -clock_step (3 *NS_PER_SEC ); +clock_step (3 *NSEC_PER_SEC );qmp_check_no_event ();/* Enable and let it fire */ outb (0x443 ,13 ); -clock_step (3 *NS_PER_SEC ); +clock_step (3 *NSEC_PER_SEC );qmp_check_no_event (); -clock_step (2 *NS_PER_SEC ); +clock_step (2 *NSEC_PER_SEC );return qmp_get_event ("WATCHDOG" ); }
util/throttle.c +2 -2
@@ -34,7 +34,7 @@ void throttle_leak_bucket(LeakyBucket *bkt, int64_t delta_ns)double leak;/* compute how much to leak */ - leak = (bkt->avg * (double ) delta_ns) /NANOSECONDS_PER_SECOND ; + leak = (bkt->avg * (double ) delta_ns) /NSEC_PER_SEC ;/* make the bucket leak */ bkt->level =MAX (bkt->level - leak,0 );
@@ -70,7 +70,7 @@ static void throttle_do_leak(ThrottleState *ts, int64_t now)*/ static int64_t throttle_do_compute_wait (double limit,double extra) { -double wait = extra *NANOSECONDS_PER_SECOND ; +double wait = extra *NSEC_PER_SEC ; wait /= limit;return wait; }
Signature · 1 line
2.1.4
PATCH 3/3 util: Infrastructure for computing recent averages
In reply to Alberto GarciaThis module computes the average of a set of values within a time window, keeping also track of the minimum and maximum values.
In order to produce more accurate results it works internally by creating two time windows of the same period, offsetted by half of that period. Values are accounted on both windows and the data is always returned from the oldest one.
--- include/qemu/timed-average.h | 58 ++++++++++++ tests/Makefile | 4 + tests/test-timed-average.c | 89 ++++++++++++++++++ util/Makefile.objs | 1 + util/timed-average.c | 208 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 360 insertions(+) create mode 100644 include/qemu/timed-average.h create mode 100644 tests/test-timed-average.c create mode 100644 util/timed-average.c
include/qemu/timed-average.h new file +58 -0
@@ -0,0 +1,58 @@ +/* +* QEMU timed average computation +* +* Copyright (C) Nodalink, EURL. 2014 +* Copyright (C) Igalia, S.L. 2015 +* +* Authors: +* Benoît Canet <[email protected]> +* Alberto Garcia <[email protected]> +* +* 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) version 3 or any later version. +* +* This program 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 General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef TIMED_AVERAGE_H +#define TIMED_AVERAGE_H + +#include <stdint.h> + +#include "qemu/timer.h" + +typedef struct TimedAverageWindow { +uint64_t min;/* minimum value accounted in the window */ +uint64_t max;/* maximum value accounted in the window */ +uint64_t sum;/* sum of all values */ +uint64_t count;/* number of values */ +int64_t expiration;/* the end of the current window in ns */ +}TimedAverageWindow ; + +typedef struct TimedAverage { +uint64_t period;/* period in nanoseconds */ +TimedAverageWindow windows[2 ];/* two overlapping windows of with +* an offset of period / 2 between them */ +unsigned current;/* the current window index: it's also the +* oldest window index */ +QEMUClockType clock_type;/* the clock used */ +}TimedAverage ; + +void timed_average_init (TimedAverage *ta,QEMUClockType clock_type, +unsigned period); + +void timed_average_account (TimedAverage *ta,uint64_t value); + +uint64_t timed_average_min (TimedAverage *ta); +uint64_t timed_average_avg (TimedAverage *ta); +uint64_t timed_average_max (TimedAverage *ta); + +#endif
tests/Makefile +4 -0
@@ -72,6 +72,7 @@ check-unit-y += tests/test-qemu-opts$(EXESUF) gcov-files-test-qemu-opts-y = qom/test-qemu-opts.c check-unit-y += tests/test-write-threshold$(EXESUF) gcov-files-test-write-threshold-y = block/write-threshold.c +check-unit-y += tests/test-timed-average$(EXESUF) check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
@@ -301,6 +302,9 @@ tests/test-vmstate$(EXESUF): tests/test-vmstate.o \ migration/qemu-file-unix.o qjson.o \ $(qom-core-obj) \ libqemuutil.a libqemustub.a +tests/test-timed-average$(EXESUF): tests/test-timed-average.o qemu-timer.o \ + libqemuutil.a stubs/clock-warp.o stubs/cpu-get-icount.o \ + stubs/notify-event.o tests/test-qapi-types.c tests/test-qapi-types.h :\ $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
tests/test-timed-average.c new file +89 -0
89 lines not on this page · raw message
util/Makefile.objs +1 -0
@@ -18,3 +18,4 @@ util-obj-y += getauxval.o util-obj-y += readline.o util-obj-y += rfifolock.o util-obj-y += rcu.o +util-obj-y += timed-average.o
util/timed-average.c new file +208 -0
208 lines not on this page · raw message
Signature · 1 line
2.1.4
Stefan Hajnoczi
AppliedQuoted 27 lines · Alberto Garcia
This series adds a new module that can be used to compute the average of a set of values in a certain period of time. This will be used by the accounting code to obtain statistics such as the min / max / average latency of I/O commands.
This is based on Benoît's code, originally written last year.
Regards,
Berto
Alberto Garcia (3):
timer: MoveNANOSECONDS_PER_SECONDStotimer.h
timer: Use a single definition ofNSEC_PER_SECfor the whole codebase
util: Infrastructure for computing recent averageshw/ppc/ppc.c | 2 - hw/ppc/spapr_rtc.c | 3 +- hw/timer/mc146818rtc.c | 1 - hw/usb/hcd-ehci.c | 2 +- include/qemu/throttle.h | 2 - include/qemu/timed-average.h | 58 ++++++++++++ include/qemu/timer.h | 2 + tests/Makefile | 4 + tests/rtl8139-test.c | 10 +-- tests/test-throttle.c | 8 +- tests/test-timed-average.c | 89 ++++++++++++++++++
Quoted 8 lines
tests/wdt_ib700-test.c | 15 ++-- util/Makefile.objs | 1 + util/throttle.c | 4 +- util/timed-average.c | 208 +++++++++++++++++++++++++++++++++++++++++++ 15 files changed, 382 insertions(+), 27 deletions(-) create mode 100644 include/qemu/timed-average.h create mode 100644 tests/test-timed-average.c create mode 100644 util/timed-average.c
Thanks, applied patches 1 & 2 to my block tree:
https://github.com/stefanha/qemu/commits/block
Patch 3 is going to be unused in QEMU 2.4 for I'm holding off on merging it. Please resend it together with the accounting series so it can be merged for QEMU 2.5.
Thanks,
Stefan
Quoted 6 lines · Stefan Hajnoczi
Thanks, applied patches 1 & 2 to my block tree:
https://github.com/stefanha/qemu/commits/blockPatch 3 is going to be unused in QEMU 2.4 for I'm holding off on merging it. Please resend it together with the accounting series so it can be merged for QEMU 2.5.
Thanks Stefan,
I'm actually about to finish the work on the accounting series. Shall I try to send it these days or should I bettter wait until QEMU 2.4 is released?
Berto