tests/migration: Introduce dirty-limit into guestperf

Currently, guestperf does not cover the dirty-limit
migration, support this feature.

Note that dirty-limit requires 'dirty-ring-size' set.

To enable dirty-limit, setting x-vcpu-dirty-limit-period
as 500ms and x-vcpu-dirty-limit as 10MB/s:
$ ./tests/migration/guestperf.py \
    --dirty-ring-size 4096 \
    --dirty-limit --x-vcpu-dirty-limit-period 500 \
    --vcpu-dirty-limit 10 --output output.json \

To run the entire standardized set of dirty-limit-enabled
comparisons, with unix migration:
$ ./tests/migration/guestperf-batch.py \
    --dirty-ring-size 4096 \
    --dst-host localhost --transport unix \
    --filter compr-dirty-limit* --output outputdir

Signed-off-by: Hyman Huang <yong.huang@smartx.com>
Reviewed-by: Fabiano Rosas <farosas@suse.de>
Message-Id: <516e7a55dfc6e33d33510be37eb24223de5dc072.1697815117.git.yong.huang@smartx.com>
Message-ID: <e1283565b00b34b0377bbd27bee4bb8fc7c255a8.1698847223.git.yong.huang@smartx.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
This commit is contained in:
Hyman Huang 2023-11-01 22:04:08 +08:00 committed by Juan Quintela
parent 4cc563d460
commit 22b7cb2c79
5 changed files with 81 additions and 4 deletions

View File

@ -135,4 +135,27 @@ COMPARISONS = [
Scenario("compr-multifd-channels-64", Scenario("compr-multifd-channels-64",
multifd=True, multifd_channels=64), multifd=True, multifd_channels=64),
]), ]),
# Looking at effect of dirty-limit with
# varying x_vcpu_dirty_limit_period
Comparison("compr-dirty-limit-period", scenarios = [
Scenario("compr-dirty-limit-period-500",
dirty_limit=True, x_vcpu_dirty_limit_period=500),
Scenario("compr-dirty-limit-period-800",
dirty_limit=True, x_vcpu_dirty_limit_period=800),
Scenario("compr-dirty-limit-period-1000",
dirty_limit=True, x_vcpu_dirty_limit_period=1000),
]),
# Looking at effect of dirty-limit with
# varying vcpu_dirty_limit
Comparison("compr-dirty-limit", scenarios = [
Scenario("compr-dirty-limit-10MB",
dirty_limit=True, vcpu_dirty_limit=10),
Scenario("compr-dirty-limit-20MB",
dirty_limit=True, vcpu_dirty_limit=20),
Scenario("compr-dirty-limit-50MB",
dirty_limit=True, vcpu_dirty_limit=50),
]),
] ]

View File

@ -102,6 +102,8 @@ class Engine(object):
info.get("expected-downtime", 0), info.get("expected-downtime", 0),
info.get("setup-time", 0), info.get("setup-time", 0),
info.get("cpu-throttle-percentage", 0), info.get("cpu-throttle-percentage", 0),
info.get("dirty-limit-throttle-time-per-round", 0),
info.get("dirty-limit-ring-full-time", 0),
) )
def _migrate(self, hardware, scenario, src, dst, connect_uri): def _migrate(self, hardware, scenario, src, dst, connect_uri):
@ -203,6 +205,21 @@ class Engine(object):
resp = dst.cmd("migrate-set-parameters", resp = dst.cmd("migrate-set-parameters",
multifd_channels=scenario._multifd_channels) multifd_channels=scenario._multifd_channels)
if scenario._dirty_limit:
if not hardware._dirty_ring_size:
raise Exception("dirty ring size must be configured when "
"testing dirty limit migration")
resp = src.cmd("migrate-set-capabilities",
capabilities = [
{ "capability": "dirty-limit",
"state": True }
])
resp = src.cmd("migrate-set-parameters",
x_vcpu_dirty_limit_period=scenario._x_vcpu_dirty_limit_period)
resp = src.cmd("migrate-set-parameters",
vcpu_dirty_limit=scenario._vcpu_dirty_limit)
resp = src.cmd("migrate", uri=connect_uri) resp = src.cmd("migrate", uri=connect_uri)
post_copy = False post_copy = False

View File

@ -81,7 +81,9 @@ class Progress(object):
downtime, downtime,
downtime_expected, downtime_expected,
setup_time, setup_time,
throttle_pcent): throttle_pcent,
dirty_limit_throttle_time_per_round,
dirty_limit_ring_full_time):
self._status = status self._status = status
self._ram = ram self._ram = ram
@ -91,6 +93,10 @@ class Progress(object):
self._downtime_expected = downtime_expected self._downtime_expected = downtime_expected
self._setup_time = setup_time self._setup_time = setup_time
self._throttle_pcent = throttle_pcent self._throttle_pcent = throttle_pcent
self._dirty_limit_throttle_time_per_round = \
dirty_limit_throttle_time_per_round
self._dirty_limit_ring_full_time = \
dirty_limit_ring_full_time
def serialize(self): def serialize(self):
return { return {
@ -102,6 +108,10 @@ class Progress(object):
"downtime_expected": self._downtime_expected, "downtime_expected": self._downtime_expected,
"setup_time": self._setup_time, "setup_time": self._setup_time,
"throttle_pcent": self._throttle_pcent, "throttle_pcent": self._throttle_pcent,
"dirty_limit_throttle_time_per_round":
self._dirty_limit_throttle_time_per_round,
"dirty_limit_ring_full_time":
self._dirty_limit_ring_full_time,
} }
@classmethod @classmethod
@ -114,4 +124,6 @@ class Progress(object):
data["downtime"], data["downtime"],
data["downtime_expected"], data["downtime_expected"],
data["setup_time"], data["setup_time"],
data["throttle_pcent"]) data["throttle_pcent"],
data["dirty_limit_throttle_time_per_round"],
data["dirty_limit_ring_full_time"])

View File

@ -30,7 +30,9 @@ class Scenario(object):
auto_converge=False, auto_converge_step=10, auto_converge=False, auto_converge_step=10,
compression_mt=False, compression_mt_threads=1, compression_mt=False, compression_mt_threads=1,
compression_xbzrle=False, compression_xbzrle_cache=10, compression_xbzrle=False, compression_xbzrle_cache=10,
multifd=False, multifd_channels=2): multifd=False, multifd_channels=2,
dirty_limit=False, x_vcpu_dirty_limit_period=500,
vcpu_dirty_limit=1):
self._name = name self._name = name
@ -60,6 +62,10 @@ class Scenario(object):
self._multifd = multifd self._multifd = multifd
self._multifd_channels = multifd_channels self._multifd_channels = multifd_channels
self._dirty_limit = dirty_limit
self._x_vcpu_dirty_limit_period = x_vcpu_dirty_limit_period
self._vcpu_dirty_limit = vcpu_dirty_limit
def serialize(self): def serialize(self):
return { return {
"name": self._name, "name": self._name,
@ -79,6 +85,9 @@ class Scenario(object):
"compression_xbzrle_cache": self._compression_xbzrle_cache, "compression_xbzrle_cache": self._compression_xbzrle_cache,
"multifd": self._multifd, "multifd": self._multifd,
"multifd_channels": self._multifd_channels, "multifd_channels": self._multifd_channels,
"dirty_limit": self._dirty_limit,
"x_vcpu_dirty_limit_period": self._x_vcpu_dirty_limit_period,
"vcpu_dirty_limit": self._vcpu_dirty_limit,
} }
@classmethod @classmethod

View File

@ -131,6 +131,17 @@ class Shell(BaseShell):
parser.add_argument("--multifd-channels", dest="multifd_channels", parser.add_argument("--multifd-channels", dest="multifd_channels",
default=2, type=int) default=2, type=int)
parser.add_argument("--dirty-limit", dest="dirty_limit", default=False,
action="store_true")
parser.add_argument("--x-vcpu-dirty-limit-period",
dest="x_vcpu_dirty_limit_period",
default=500, type=int)
parser.add_argument("--vcpu-dirty-limit",
dest="vcpu_dirty_limit",
default=1, type=int)
def get_scenario(self, args): def get_scenario(self, args):
return Scenario(name="perfreport", return Scenario(name="perfreport",
downtime=args.downtime, downtime=args.downtime,
@ -154,7 +165,12 @@ class Shell(BaseShell):
compression_xbzrle_cache=args.compression_xbzrle_cache, compression_xbzrle_cache=args.compression_xbzrle_cache,
multifd=args.multifd, multifd=args.multifd,
multifd_channels=args.multifd_channels) multifd_channels=args.multifd_channels,
dirty_limit=args.dirty_limit,
x_vcpu_dirty_limit_period=\
args.x_vcpu_dirty_limit_period,
vcpu_dirty_limit=args.vcpu_dirty_limit)
def run(self, argv): def run(self, argv):
args = self._parser.parse_args(argv) args = self._parser.parse_args(argv)