block: Add average I/O queue depth to BlockDeviceTimedStats
This patch adds two new fields to BlockDeviceTimedStats that track the average number of pending read and write requests for a block device. The values are calculated for the period of time defined for that interval. Signed-off-by: Alberto Garcia <berto@igalia.com> Message-id: fd31fef53e2714f2f30d59ed58ca2f67ec9ab926.1446044837.git.berto@igalia.com Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
979e9b03fc
commit
96e4dedaff
@ -143,3 +143,15 @@ int64_t block_acct_idle_time_ns(BlockAcctStats *stats)
|
||||
{
|
||||
return qemu_clock_get_ns(clock_type) - stats->last_access_time_ns;
|
||||
}
|
||||
|
||||
double block_acct_queue_depth(BlockAcctTimedStats *stats,
|
||||
enum BlockAcctType type)
|
||||
{
|
||||
uint64_t sum, elapsed;
|
||||
|
||||
assert(type < BLOCK_MAX_IOTYPE);
|
||||
|
||||
sum = timed_average_sum(&stats->latency[type], &elapsed);
|
||||
|
||||
return (double) sum / elapsed;
|
||||
}
|
||||
|
@ -402,6 +402,11 @@ static BlockStats *bdrv_query_stats(const BlockDriverState *bs,
|
||||
dev_stats->min_flush_latency_ns = timed_average_min(fl);
|
||||
dev_stats->max_flush_latency_ns = timed_average_max(fl);
|
||||
dev_stats->avg_flush_latency_ns = timed_average_avg(fl);
|
||||
|
||||
dev_stats->avg_rd_queue_depth =
|
||||
block_acct_queue_depth(ts, BLOCK_ACCT_READ);
|
||||
dev_stats->avg_wr_queue_depth =
|
||||
block_acct_queue_depth(ts, BLOCK_ACCT_WRITE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,5 +78,7 @@ void block_acct_invalid(BlockAcctStats *stats, enum BlockAcctType type);
|
||||
void block_acct_merge_done(BlockAcctStats *stats, enum BlockAcctType type,
|
||||
int num_requests);
|
||||
int64_t block_acct_idle_time_ns(BlockAcctStats *stats);
|
||||
double block_acct_queue_depth(BlockAcctTimedStats *stats,
|
||||
enum BlockAcctType type);
|
||||
|
||||
#endif
|
||||
|
@ -59,5 +59,6 @@ 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);
|
||||
uint64_t timed_average_sum(TimedAverage *ta, uint64_t *elapsed);
|
||||
|
||||
#endif
|
||||
|
@ -450,6 +450,12 @@
|
||||
# @avg_flush_latency_ns: Average latency of flush operations in the
|
||||
# defined interval, in nanoseconds.
|
||||
#
|
||||
# @avg_rd_queue_depth: Average number of pending read operations
|
||||
# in the defined interval.
|
||||
#
|
||||
# @avg_wr_queue_depth: Average number of pending write operations
|
||||
# in the defined interval.
|
||||
#
|
||||
# Since: 2.5
|
||||
##
|
||||
|
||||
@ -458,7 +464,8 @@
|
||||
'max_rd_latency_ns': 'int', 'avg_rd_latency_ns': 'int',
|
||||
'min_wr_latency_ns': 'int', 'max_wr_latency_ns': 'int',
|
||||
'avg_wr_latency_ns': 'int', 'min_flush_latency_ns': 'int',
|
||||
'max_flush_latency_ns': 'int', 'avg_flush_latency_ns': 'int' } }
|
||||
'max_flush_latency_ns': 'int', 'avg_flush_latency_ns': 'int',
|
||||
'avg_rd_queue_depth': 'number', 'avg_wr_queue_depth': 'number' } }
|
||||
|
||||
##
|
||||
# @BlockDeviceStats:
|
||||
|
@ -2635,6 +2635,12 @@ Each json-object contain the following:
|
||||
- "avg_flush_latency_ns": average latency of flush operations
|
||||
in the defined interval, in
|
||||
nanoseconds (json-int)
|
||||
- "avg_rd_queue_depth": average number of pending read
|
||||
operations in the defined interval
|
||||
(json-number)
|
||||
- "avg_wr_queue_depth": average number of pending write
|
||||
operations in the defined interval
|
||||
(json-number).
|
||||
- "parent": Contains recursively the statistics of the underlying
|
||||
protocol (e.g. the host file for a qcow2 image). If there is
|
||||
no underlying protocol, this field is omitted
|
||||
|
@ -120,8 +120,10 @@ void timed_average_init(TimedAverage *ta, QEMUClockType clock_type,
|
||||
* expiration time if that's the case.
|
||||
*
|
||||
* @ta: the TimedAverage structure
|
||||
* @elapsed: if non-NULL, the elapsed time (in ns) within the current
|
||||
* window will be stored here
|
||||
*/
|
||||
static void check_expirations(TimedAverage *ta)
|
||||
static void check_expirations(TimedAverage *ta, uint64_t *elapsed)
|
||||
{
|
||||
int64_t now = qemu_clock_get_ns(ta->clock_type);
|
||||
int i;
|
||||
@ -143,6 +145,12 @@ static void check_expirations(TimedAverage *ta)
|
||||
} else {
|
||||
ta->current = 1;
|
||||
}
|
||||
|
||||
/* Calculate the elapsed time within the current window */
|
||||
if (elapsed) {
|
||||
int64_t remaining = ta->windows[ta->current].expiration - now;
|
||||
*elapsed = ta->period - remaining;
|
||||
}
|
||||
}
|
||||
|
||||
/* Account a value
|
||||
@ -153,7 +161,7 @@ static void check_expirations(TimedAverage *ta)
|
||||
void timed_average_account(TimedAverage *ta, uint64_t value)
|
||||
{
|
||||
int i;
|
||||
check_expirations(ta);
|
||||
check_expirations(ta, NULL);
|
||||
|
||||
/* Do the accounting in both windows at the same time */
|
||||
for (i = 0; i < 2; i++) {
|
||||
@ -180,7 +188,7 @@ void timed_average_account(TimedAverage *ta, uint64_t value)
|
||||
uint64_t timed_average_min(TimedAverage *ta)
|
||||
{
|
||||
TimedAverageWindow *w;
|
||||
check_expirations(ta);
|
||||
check_expirations(ta, NULL);
|
||||
w = current_window(ta);
|
||||
return w->min < UINT64_MAX ? w->min : 0;
|
||||
}
|
||||
@ -193,7 +201,7 @@ uint64_t timed_average_min(TimedAverage *ta)
|
||||
uint64_t timed_average_avg(TimedAverage *ta)
|
||||
{
|
||||
TimedAverageWindow *w;
|
||||
check_expirations(ta);
|
||||
check_expirations(ta, NULL);
|
||||
w = current_window(ta);
|
||||
return w->count > 0 ? w->sum / w->count : 0;
|
||||
}
|
||||
@ -205,6 +213,19 @@ uint64_t timed_average_avg(TimedAverage *ta)
|
||||
*/
|
||||
uint64_t timed_average_max(TimedAverage *ta)
|
||||
{
|
||||
check_expirations(ta);
|
||||
check_expirations(ta, NULL);
|
||||
return current_window(ta)->max;
|
||||
}
|
||||
|
||||
/* Get the sum of all accounted values
|
||||
* @ta: the TimedAverage structure
|
||||
* @elapsed: if non-NULL, the elapsed time (in ns) will be stored here
|
||||
* @ret: the sum of all accounted values
|
||||
*/
|
||||
uint64_t timed_average_sum(TimedAverage *ta, uint64_t *elapsed)
|
||||
{
|
||||
TimedAverageWindow *w;
|
||||
check_expirations(ta, elapsed);
|
||||
w = current_window(ta);
|
||||
return w->sum;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user