Browse Source
Benchmark for new preallocate filter.
Example usage:
./bench_prealloc.py ../../build/qemu-img \
ssd-ext4:/path/to/mount/point \
ssd-xfs:/path2 hdd-ext4:/path3 hdd-xfs:/path4
The benchmark shows performance improvement (or degradation) when use
new preallocate filter with qcow2 image.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20201021145859.11201-22-vsementsov@virtuozzo.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Max Reitz <mreitz@redhat.com>
pull/105/head
committed by
Max Reitz
1 changed files with 132 additions and 0 deletions
@ -0,0 +1,132 @@ |
|||
#!/usr/bin/env python3 |
|||
# |
|||
# Benchmark preallocate filter |
|||
# |
|||
# 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 re |
|||
import json |
|||
|
|||
import simplebench |
|||
from results_to_text import results_to_text |
|||
|
|||
|
|||
def qemu_img_bench(args): |
|||
p = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, |
|||
universal_newlines=True) |
|||
|
|||
if p.returncode == 0: |
|||
try: |
|||
m = re.search(r'Run completed in (\d+.\d+) seconds.', p.stdout) |
|||
return {'seconds': float(m.group(1))} |
|||
except Exception: |
|||
return {'error': f'failed to parse qemu-img output: {p.stdout}'} |
|||
else: |
|||
return {'error': f'qemu-img failed: {p.returncode}: {p.stdout}'} |
|||
|
|||
|
|||
def bench_func(env, case): |
|||
fname = f"{case['dir']}/prealloc-test.qcow2" |
|||
try: |
|||
os.remove(fname) |
|||
except OSError: |
|||
pass |
|||
|
|||
subprocess.run([env['qemu-img-binary'], 'create', '-f', 'qcow2', fname, |
|||
'16G'], stdout=subprocess.DEVNULL, |
|||
stderr=subprocess.DEVNULL, check=True) |
|||
|
|||
args = [env['qemu-img-binary'], 'bench', '-c', str(case['count']), |
|||
'-d', '64', '-s', case['block-size'], '-t', 'none', '-n', '-w'] |
|||
if env['prealloc']: |
|||
args += ['--image-opts', |
|||
'driver=qcow2,file.driver=preallocate,file.file.driver=file,' |
|||
f'file.file.filename={fname}'] |
|||
else: |
|||
args += ['-f', 'qcow2', fname] |
|||
|
|||
return qemu_img_bench(args) |
|||
|
|||
|
|||
def auto_count_bench_func(env, case): |
|||
case['count'] = 100 |
|||
while True: |
|||
res = bench_func(env, case) |
|||
if 'error' in res: |
|||
return res |
|||
|
|||
if res['seconds'] >= 1: |
|||
break |
|||
|
|||
case['count'] *= 10 |
|||
|
|||
if res['seconds'] < 5: |
|||
case['count'] = round(case['count'] * 5 / res['seconds']) |
|||
res = bench_func(env, case) |
|||
if 'error' in res: |
|||
return res |
|||
|
|||
res['iops'] = case['count'] / res['seconds'] |
|||
return res |
|||
|
|||
|
|||
if __name__ == '__main__': |
|||
if len(sys.argv) < 2: |
|||
print(f'USAGE: {sys.argv[0]} <qemu-img binary> ' |
|||
'DISK_NAME:DIR_PATH ...') |
|||
exit(1) |
|||
|
|||
qemu_img = sys.argv[1] |
|||
|
|||
envs = [ |
|||
{ |
|||
'id': 'no-prealloc', |
|||
'qemu-img-binary': qemu_img, |
|||
'prealloc': False |
|||
}, |
|||
{ |
|||
'id': 'prealloc', |
|||
'qemu-img-binary': qemu_img, |
|||
'prealloc': True |
|||
} |
|||
] |
|||
|
|||
aligned_cases = [] |
|||
unaligned_cases = [] |
|||
|
|||
for disk in sys.argv[2:]: |
|||
name, path = disk.split(':') |
|||
aligned_cases.append({ |
|||
'id': f'{name}, aligned sequential 16k', |
|||
'block-size': '16k', |
|||
'dir': path |
|||
}) |
|||
unaligned_cases.append({ |
|||
'id': f'{name}, unaligned sequential 64k', |
|||
'block-size': '16k', |
|||
'dir': path |
|||
}) |
|||
|
|||
result = simplebench.bench(auto_count_bench_func, envs, |
|||
aligned_cases + unaligned_cases, count=5) |
|||
print(results_to_text(result)) |
|||
with open('results.json', 'w') as f: |
|||
json.dump(result, f, indent=4) |
|||
Loading…
Reference in new issue