All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, qemu-devel@nongnu.org
Subject: [Qemu-devel] [PULL 29/34] docs: Document the throttling infrastructure
Date: Mon, 22 Feb 2016 17:32:47 +0100	[thread overview]
Message-ID: <1456158772-9344-30-git-send-email-kwolf@redhat.com> (raw)
In-Reply-To: <1456158772-9344-1-git-send-email-kwolf@redhat.com>

From: Alberto Garcia <berto@igalia.com>

Signed-off-by: Alberto Garcia <berto@igalia.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 docs/throttle.txt | 252 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 252 insertions(+)
 create mode 100644 docs/throttle.txt

diff --git a/docs/throttle.txt b/docs/throttle.txt
new file mode 100644
index 0000000..28204e4
--- /dev/null
+++ b/docs/throttle.txt
@@ -0,0 +1,252 @@
+The QEMU throttling infrastructure
+==================================
+Copyright (C) 2016 Igalia, S.L.
+Author: Alberto Garcia <berto@igalia.com>
+
+This work is licensed under the terms of the GNU GPL, version 2 or
+later. See the COPYING file in the top-level directory.
+
+Introduction
+------------
+QEMU includes a throttling module that can be used to set limits to
+I/O operations. The code itself is generic and independent of the I/O
+units, but it is currenly used to limit the number of bytes per second
+and operations per second (IOPS) when performing disk I/O.
+
+This document explains how to use the throttling code in QEMU, and how
+it works internally. The implementation is in throttle.c.
+
+
+Using throttling to limit disk I/O
+----------------------------------
+Two aspects of the disk I/O can be limited: the number of bytes per
+second and the number of operations per second (IOPS). For each one of
+them the user can set a global limit or separate limits for read and
+write operations. This gives us a total of six different parameters.
+
+I/O limits can be set using the throttling.* parameters of -drive, or
+using the QMP 'block_set_io_throttle' command. These are the names of
+the parameters for both cases:
+
+|-----------------------+-----------------------|
+| -drive                | block_set_io_throttle |
+|-----------------------+-----------------------|
+| throttling.iops-total | iops                  |
+| throttling.iops-read  | iops_rd               |
+| throttling.iops-write | iops_wr               |
+| throttling.bps-total  | bps                   |
+| throttling.bps-read   | bps_rd                |
+| throttling.bps-write  | bps_wr                |
+|-----------------------+-----------------------|
+
+It is possible to set limits for both IOPS and bps and the same time,
+and for each case we can decide whether to have separate read and
+write limits or not, but note that if iops-total is set then neither
+iops-read nor iops-write can be set. The same applies to bps-total and
+bps-read/write.
+
+The default value of these parameters is 0, and it means 'unlimited'.
+
+In its most basic usage, the user can add a drive to QEMU with a limit
+of 100 IOPS with the following -drive line:
+
+   -drive file=hd0.qcow2,throttling.iops-total=100
+
+We can do the same using QMP. In this case all these parameters are
+mandatory, so we must set to 0 the ones that we don't want to limit:
+
+   { "execute": "block_set_io_throttle",
+     "arguments": {
+        "device": "virtio0",
+        "iops": 100,
+        "iops_rd": 0,
+        "iops_wr": 0,
+        "bps": 0,
+        "bps_rd": 0,
+        "bps_wr": 0
+     }
+   }
+
+
+I/O bursts
+----------
+In addition to the basic limits we have just seen, QEMU allows the
+user to do bursts of I/O for a configurable amount of time. A burst is
+an amount of I/O that can exceed the basic limit. Bursts are useful to
+allow better performance when there are peaks of activity (the OS
+boots, a service needs to be restarted) while keeping the average
+limits lower the rest of the time.
+
+Two parameters control bursts: their length and the maximum amount of
+I/O they allow. These two can be configured separately for each one of
+the six basic parameters described in the previous section, but in
+this section we'll use 'iops-total' as an example.
+
+The I/O limit during bursts is set using 'iops-total-max', and the
+maximum length (in seconds) is set with 'iops-total-max-length'. So if
+we want to configure a drive with a basic limit of 100 IOPS and allow
+bursts of 2000 IOPS for 60 seconds, we would do it like this (the line
+is split for clarity):
+
+   -drive file=hd0.qcow2,
+          throttling.iops-total=100,
+          throttling.iops-total-max=2000,
+          throttling.iops-total-max-length=60
+
+Or, with QMP:
+
+   { "execute": "block_set_io_throttle",
+     "arguments": {
+        "device": "virtio0",
+        "iops": 100,
+        "iops_rd": 0,
+        "iops_wr": 0,
+        "bps": 0,
+        "bps_rd": 0,
+        "bps_wr": 0,
+        "iops_max": 2000,
+        "iops_max_length": 60,
+     }
+   }
+
+With this, the user can perform I/O on hd0.qcow2 at a rate of 2000
+IOPS for 1 minute before it's throttled down to 100 IOPS.
+
+The user will be able to do bursts again if there's a sufficiently
+long period of time with unused I/O (see below for details).
+
+The default value for 'iops-total-max' is 0 and it means that bursts
+are not allowed. 'iops-total-max-length' can only be set if
+'iops-total-max' is set as well, and its default value is 1 second.
+
+Here's the complete list of parameters for configuring bursts:
+
+|----------------------------------+-----------------------|
+| -drive                           | block_set_io_throttle |
+|----------------------------------+-----------------------|
+| throttling.iops-total-max        | iops_max              |
+| throttling.iops-total-max-length | iops_max_length       |
+| throttling.iops-read-max         | iops_rd_max           |
+| throttling.iops-read-max-length  | iops_rd_max_length    |
+| throttling.iops-write-max        | iops_wr_max           |
+| throttling.iops-write-max-length | iops_wr_max_length    |
+| throttling.bps-total-max         | bps_max               |
+| throttling.bps-total-max-length  | bps_max_length        |
+| throttling.bps-read-max          | bps_rd_max            |
+| throttling.bps-read-max-length   | bps_rd_max_length     |
+| throttling.bps-write-max         | bps_wr_max            |
+| throttling.bps-write-max-length  | bps_wr_max_length     |
+|----------------------------------+-----------------------|
+
+
+Controlling the size of I/O operations
+--------------------------------------
+When applying IOPS limits all I/O operations are treated equally
+regardless of their size. This means that the user can take advantage
+of this in order to circumvent the limits and submit one huge I/O
+request instead of several smaller ones.
+
+QEMU provides a setting called throttling.iops-size to prevent this
+from happening. This setting specifies the size (in bytes) of an I/O
+request for accounting purposes. Larger requests will be counted
+proportionally to this size.
+
+For example, if iops-size is set to 4096 then an 8KB request will be
+counted as two, and a 6KB request will be counted as one and a
+half. This only applies to requests larger than iops-size: smaller
+requests will be always counted as one, no matter their size.
+
+The default value of iops-size is 0 and it means that the size of the
+requests is never taken into account when applying IOPS limits.
+
+
+Applying I/O limits to groups of disks
+--------------------------------------
+In all the examples so far we have seen how to apply limits to the I/O
+performed on individual drives, but QEMU allows grouping drives so
+they all share the same limits.
+
+The way it works is that each drive with I/O limits is assigned to a
+group named using the throttling.group parameter. If this parameter is
+not specified, then the device name (i.e. 'virtio0', 'ide0-hd0') will
+be used as the group name.
+
+Limits set using the throttling.* parameters discussed earlier in this
+document apply to the combined I/O of all members of a group.
+
+Consider this example:
+
+   -drive file=hd1.qcow2,throttling.iops-total=6000,throttling.group=foo
+   -drive file=hd2.qcow2,throttling.iops-total=6000,throttling.group=foo
+   -drive file=hd3.qcow2,throttling.iops-total=3000,throttling.group=bar
+   -drive file=hd4.qcow2,throttling.iops-total=6000,throttling.group=foo
+   -drive file=hd5.qcow2,throttling.iops-total=3000,throttling.group=bar
+   -drive file=hd6.qcow2,throttling.iops-total=5000
+
+Here hd1, hd2 and hd4 are all members of a group named 'foo' with a
+combined IOPS limit of 6000, and hd3 and hd5 are members of 'bar'. hd6
+is left alone (technically it is part of a 1-member group).
+
+Limits are applied in a round-robin fashion so if there are concurrent
+I/O requests on several drives of the same group they will be
+distributed evenly.
+
+When I/O limits are applied to an existing drive using the QMP command
+'block_set_io_throttle', the following things need to be taken into
+account:
+
+   - I/O limits are shared within the same group, so new values will
+     affect all members and overwrite the previous settings. In other
+     words: if different limits are applied to members of the same
+     group, the last one wins.
+
+   - If 'group' is unset it is assumed to be the current group of that
+     drive. If the drive is not in a group yet, it will be added to a
+     group named after the device name.
+
+   - If 'group' is set then the drive will be moved to that group if
+     it was member of a different one. In this case the limits
+     specified in the parameters will be applied to the new group
+     only.
+
+   - I/O limits can be disabled by setting all of them to 0. In this
+     case the device will be removed from its group and the rest of
+     its members will not be affected. The 'group' parameter is
+     ignored.
+
+
+The Leaky Bucket algorithm
+--------------------------
+I/O limits in QEMU are implemented using the leaky bucket algorithm
+(specifically the "Leaky bucket as a meter" variant).
+
+This algorithm uses the analogy of a bucket that leaks water
+constantly. The water that gets into the bucket represents the I/O
+that has been performed, and no more I/O is allowed once the bucket is
+full.
+
+To see the way this corresponds to the throttling parameters in QEMU,
+consider the following values:
+
+  iops-total=100
+  iops-total-max=2000
+  iops-total-max-length=60
+
+  - Water leaks from the bucket at a rate of 100 IOPS.
+  - Water can be added to the bucket at a rate of 2000 IOPS.
+  - The size of the bucket is 2000 x 60 = 120000
+  - If 'iops-total-max-length' is unset then the bucket size is 100.
+
+The bucket is initially empty, therefore water can be added until it's
+full at a rate of 2000 IOPS (the burst rate). Once the bucket is full
+we can only add as much water as it leaks, therefore the I/O rate is
+reduced to 100 IOPS. If we add less water than it leaks then the
+bucket will start to empty, allowing for bursts again.
+
+Note that since water is leaking from the bucket even during bursts,
+it will take a bit more than 60 seconds at 2000 IOPS to fill it
+up. After those 60 seconds the bucket will have leaked 60 x 100 =
+6000, allowing for 3 more seconds of I/O at 2000 IOPS.
+
+Also, due to the way the algorithm works, longer burst can be done at
+a lower I/O rate, e.g. 1000 IOPS during 120 seconds.
-- 
1.8.3.1

  parent reply	other threads:[~2016-02-22 16:33 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-22 16:32 [Qemu-devel] [PULL 00/34] Block layer patches Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 01/34] qemu-img: initialize MapEntry object Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 02/34] quorum: fix segfault when read fails in fifo mode Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 03/34] spec: add qcow2 bitmaps extension specification Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 04/34] block: Fix -incoming with snapshot=on Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 05/34] qemu-io: add support for --object command line arg Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 06/34] qemu-img: " Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 07/34] qemu-io: allow specifying image as a set of options args Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 08/34] qemu-nbd: " Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 09/34] qemu-img: " Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 10/34] qemu-nbd: don't overlap long option values with short options Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 11/34] qemu-nbd: use no_argument/required_argument constants Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 12/34] qemu-io: " Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 13/34] block migration: Activate image on destination before writing to it Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 14/34] throttle: Make throttle_compute_timer() static Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 15/34] throttle: Make throttle_conflicting() set errp Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 16/34] throttle: Make throttle_max_is_missing_limit() " Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 17/34] throttle: Make throttle_is_valid() " Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 18/34] throttle: Set always an average value when setting a maximum value Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 19/34] throttle: Merge all functions that check the configuration into one Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 20/34] throttle: Use throttle_config_init() to initialize ThrottleConfig Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 21/34] throttle: Add support for burst periods Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 22/34] throttle: Add command-line settings to define the " Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 23/34] qapi: Add burst length parameters to block_set_io_throttle Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 24/34] qapi: Add burst length fields to BlockDeviceInfo Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 25/34] throttle: Check that burst_level leaks correctly Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 26/34] throttle: Test throttle_compute_wait() during bursts Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 27/34] qemu-iotests: Extend iotest 093 to test bursts Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 28/34] qapi: Correct the name of the iops_rd parameter Kevin Wolf
2016-02-22 16:32 ` Kevin Wolf [this message]
2016-02-22 16:32 ` [Qemu-devel] [PULL 30/34] MAINTAINERS: Add myself as maintainer of the throttling code Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 31/34] blockdev: unset inappropriate flags when changing medium Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 32/34] qemu-iotests: 067: ignore QMP events Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 33/34] qemu-iotests: 140: don't use IDE device Kevin Wolf
2016-02-22 16:32 ` [Qemu-devel] [PULL 34/34] qemu-iotests: 140: make description slightly more verbose Kevin Wolf
2016-02-22 17:46 ` [Qemu-devel] [PULL 00/34] Block layer patches Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1456158772-9344-30-git-send-email-kwolf@redhat.com \
    --to=kwolf@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.