Python queue, 2020-09-18
Alexey Kirillov (1): analyze-migration.py: fix read_migration_debug_json() return type Andrey Shinkevich (1): scripts/simplebench: compare write request performance -----BEGIN PGP SIGNATURE----- iQJIBAABCAAyFiEEWjIv1avE09usz9GqKAeTb5hNxaYFAl9k9hgUHGVoYWJrb3N0 QHJlZGhhdC5jb20ACgkQKAeTb5hNxabJWRAAgMdbCeJztz47wp8DKZCvdJNfoXMJ h+38VedmcSpqy4hOuRK21a9bq8kkOKNT+UW6Uj1qAZc4/Ht4Uoc/wbpORueZIddz olULMVQJ1FjQqgdrFfCqtxf9nSVu3lkP/rXZGW0BGB7s8dab436F/1CKJqONEmQE R3xPodBxAMaqbQOhHQXjTp1YmEOSEb0j/gj7zXJ0BXZTmslCIT4zOG4nv3k7UAM/ K/HCPBVroALtCMeQeAw5FeCiff6haw09QwnTns04QWc1mZPAWqbwF5JdRCJ0iaId 3GyCYM33YYJ2c07ALh7jjmHZ4gR33unGS+NL3VjCOnzqnXuIGrw4oIss+ViCY8vR gz/OS/TMxFuNi0EHuqKNmuP8IbppoqQ1XyT40cOOxYlk7TAR5nMDP1DfJ5xF8eSG KAIV1Jqt/xGuTefpkRm/skZJOcX/7cZMB+pTJ0gw4bFbhb/y2H8PZBk+cvLpd7tE j21Fh4oFu+FuvWfiV0fEfvLsVV1O5ODn6EcfgJNldtJ3qCILM8nubfnaU4Ptwk8u saiJeXY9Sw9GpILlhC2+HQcBJ6SvvbSqPPahzqiLQeXEU0mdUTA+1f+1sLXjHiIj Nfb5SAQAgOIG/FePcUOe3e51vQRDMe+JVAJKRyXz+/B8r2zZZARwhCva+MB65YNP QtKaeeWago3PXDo= =s0SG -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/ehabkost/tags/python-next-pull-request' into staging Python queue, 2020-09-18 Alexey Kirillov (1): analyze-migration.py: fix read_migration_debug_json() return type Andrey Shinkevich (1): scripts/simplebench: compare write request performance # gpg: Signature made Fri 18 Sep 2020 19:02:00 BST # gpg: using RSA key 5A322FD5ABC4D3DBACCFD1AA2807936F984DC5A6 # gpg: issuer "ehabkost@redhat.com" # gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>" [full] # Primary key fingerprint: 5A32 2FD5 ABC4 D3DB ACCF D1AA 2807 936F 984D C5A6 * remotes/ehabkost/tags/python-next-pull-request: analyze-migration.py: fix read_migration_debug_json() return type scripts/simplebench: compare write request performance Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
5536c19d91
@ -97,7 +97,8 @@ class MigrationFile(object):
|
|||||||
# Seek back to where we were at the beginning
|
# Seek back to where we were at the beginning
|
||||||
self.file.seek(entrypos, 0)
|
self.file.seek(entrypos, 0)
|
||||||
|
|
||||||
return data[jsonpos:jsonpos + jsonlen]
|
# explicit decode() needed for Python 3.5 compatibility
|
||||||
|
return data[jsonpos:jsonpos + jsonlen].decode("utf-8")
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
self.file.close()
|
self.file.close()
|
||||||
|
170
scripts/simplebench/bench_write_req.py
Executable file
170
scripts/simplebench/bench_write_req.py
Executable file
@ -0,0 +1,170 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
#
|
||||||
|
# Test to compare performance of write requests for two qemu-img binary files.
|
||||||
|
#
|
||||||
|
# The idea of the test comes from intention to check the benefit of c8bb23cbdbe
|
||||||
|
# "qcow2: skip writing zero buffers to empty COW areas".
|
||||||
|
#
|
||||||
|
# Copyright (c) 2020 Virtuozzo International GmbH.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import simplebench
|
||||||
|
|
||||||
|
|
||||||
|
def bench_func(env, case):
|
||||||
|
""" Handle one "cell" of benchmarking table. """
|
||||||
|
return bench_write_req(env['qemu_img'], env['image_name'],
|
||||||
|
case['block_size'], case['block_offset'],
|
||||||
|
case['cluster_size'])
|
||||||
|
|
||||||
|
|
||||||
|
def qemu_img_pipe(*args):
|
||||||
|
'''Run qemu-img and return its output'''
|
||||||
|
subp = subprocess.Popen(list(args),
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.STDOUT,
|
||||||
|
universal_newlines=True)
|
||||||
|
exitcode = subp.wait()
|
||||||
|
if exitcode < 0:
|
||||||
|
sys.stderr.write('qemu-img received signal %i: %s\n'
|
||||||
|
% (-exitcode, ' '.join(list(args))))
|
||||||
|
return subp.communicate()[0]
|
||||||
|
|
||||||
|
|
||||||
|
def bench_write_req(qemu_img, image_name, block_size, block_offset,
|
||||||
|
cluster_size):
|
||||||
|
"""Benchmark write requests
|
||||||
|
|
||||||
|
The function creates a QCOW2 image with the given path/name. Then it runs
|
||||||
|
the 'qemu-img bench' command and makes series of write requests on the
|
||||||
|
image clusters. Finally, it returns the total time of the write operations
|
||||||
|
on the disk.
|
||||||
|
|
||||||
|
qemu_img -- path to qemu_img executable file
|
||||||
|
image_name -- QCOW2 image name to create
|
||||||
|
block_size -- size of a block to write to clusters
|
||||||
|
block_offset -- offset of the block in clusters
|
||||||
|
cluster_size -- size of the image cluster
|
||||||
|
|
||||||
|
Returns {'seconds': int} on success and {'error': str} on failure.
|
||||||
|
Return value is compatible with simplebench lib.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not os.path.isfile(qemu_img):
|
||||||
|
print(f'File not found: {qemu_img}')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
image_dir = os.path.dirname(os.path.abspath(image_name))
|
||||||
|
if not os.path.isdir(image_dir):
|
||||||
|
print(f'Path not found: {image_name}')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
image_size = 1024 * 1024 * 1024
|
||||||
|
|
||||||
|
args_create = [qemu_img, 'create', '-f', 'qcow2', '-o',
|
||||||
|
f'cluster_size={cluster_size}',
|
||||||
|
image_name, str(image_size)]
|
||||||
|
|
||||||
|
count = int(image_size / cluster_size) - 1
|
||||||
|
step = str(cluster_size)
|
||||||
|
|
||||||
|
args_bench = [qemu_img, 'bench', '-w', '-n', '-t', 'none', '-c',
|
||||||
|
str(count), '-s', f'{block_size}', '-o', str(block_offset),
|
||||||
|
'-S', step, '-f', 'qcow2', image_name]
|
||||||
|
|
||||||
|
try:
|
||||||
|
qemu_img_pipe(*args_create)
|
||||||
|
except OSError as e:
|
||||||
|
os.remove(image_name)
|
||||||
|
return {'error': 'qemu_img create failed: ' + str(e)}
|
||||||
|
|
||||||
|
try:
|
||||||
|
ret = qemu_img_pipe(*args_bench)
|
||||||
|
except OSError as e:
|
||||||
|
os.remove(image_name)
|
||||||
|
return {'error': 'qemu_img bench failed: ' + str(e)}
|
||||||
|
|
||||||
|
os.remove(image_name)
|
||||||
|
|
||||||
|
if 'seconds' in ret:
|
||||||
|
ret_list = ret.split()
|
||||||
|
index = ret_list.index('seconds.')
|
||||||
|
return {'seconds': float(ret_list[index-1])}
|
||||||
|
else:
|
||||||
|
return {'error': 'qemu_img bench failed: ' + ret}
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
if len(sys.argv) < 4:
|
||||||
|
program = os.path.basename(sys.argv[0])
|
||||||
|
print(f'USAGE: {program} <path to qemu-img binary file> '
|
||||||
|
'<path to another qemu-img to compare performance with> '
|
||||||
|
'<full or relative name for QCOW2 image to create>')
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
# Test-cases are "rows" in benchmark resulting table, 'id' is a caption
|
||||||
|
# for the row, other fields are handled by bench_func.
|
||||||
|
test_cases = [
|
||||||
|
{
|
||||||
|
'id': '<cluster front>',
|
||||||
|
'block_size': 4096,
|
||||||
|
'block_offset': 0,
|
||||||
|
'cluster_size': 1048576
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'id': '<cluster middle>',
|
||||||
|
'block_size': 4096,
|
||||||
|
'block_offset': 524288,
|
||||||
|
'cluster_size': 1048576
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'id': '<cross cluster>',
|
||||||
|
'block_size': 1048576,
|
||||||
|
'block_offset': 4096,
|
||||||
|
'cluster_size': 1048576
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'id': '<cluster 64K>',
|
||||||
|
'block_size': 4096,
|
||||||
|
'block_offset': 0,
|
||||||
|
'cluster_size': 65536
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
# Test-envs are "columns" in benchmark resulting table, 'id is a caption
|
||||||
|
# for the column, other fields are handled by bench_func.
|
||||||
|
# Set the paths below to desired values
|
||||||
|
test_envs = [
|
||||||
|
{
|
||||||
|
'id': '<qemu-img binary 1>',
|
||||||
|
'qemu_img': f'{sys.argv[1]}',
|
||||||
|
'image_name': f'{sys.argv[3]}'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'id': '<qemu-img binary 2>',
|
||||||
|
'qemu_img': f'{sys.argv[2]}',
|
||||||
|
'image_name': f'{sys.argv[3]}'
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
result = simplebench.bench(bench_func, test_envs, test_cases, count=3,
|
||||||
|
initial_run=False)
|
||||||
|
print(simplebench.ascii(result))
|
Loading…
Reference in New Issue
Block a user