提交 e5791c92 编写于 作者: X Xu Han 提交者: GitHub

Merge pull request #961 from YanhuiMa/block_perf

fio_perf: add fio performance test for block
- fio_perf:
only x86_64
type = fio_perf
numa_node = -1
block_size = "4k 16k 64k 256k"
format = False
iodepth = "1 8 64"
threads = "16"
rw = "read write randread randwrite randrw"
Host_RHEL:
kvm_ver_chk_cmd = "rpm -qa qemu-kvm-rhev && rpm -qa qemu-kvm"
Linux:
no ide
pattern = ".*[read|write].*bw=(\d+(?:\.\d+)?[\w|\s]B/s),\siops=(\d+).*"
order_list = "Block_size Iodepth Threads BW(MB/S) IOPS Latency(ms) Host_CPU BW/CPU KVM_Exits Util%"
guest_ver_cmd = "uname -r"
compile_cmd = "make && make install"
pre_cmd = "i=`/bin/ls /dev/[vs]db` && mkfs.xfs $i > /dev/null; partprobe; umount /mnt; mount $i /mnt"
drop_cache = "sync && echo 3 > /proc/sys/vm/drop_caches"
guest_result_file = /tmp/fio_result
fio_cmd = "fio --rw=%s --bs=%s --iodepth=%s --runtime=1m --direct=1 --filename=/mnt/%s --name=job1 --ioengine=libaio --thread --group_reporting --numjobs=%s --size=512MB --time_based --output=/tmp/fio_result &> /dev/null"
Windows:
guest_ver_cmd = wmic datafile where name="c:\\windows\\system32\\drivers\\viostor.sys" || wmic datafile where name="c:\\windows\\system32\\drivers\\vioscsi.sys"
pattern = ".*?\s{2}[read|write].*?bw=(\d+(?:\.\d+)?[\w|\s]B/s),\siops=(\d+)"
order_list = "Block_size Iodepth Threads BW(MB/S) IOPS Latency(ms) Host_CPU BW/CPU KVM_Exits"
pre_cmd = "echo select disk 1 > imDiskpart.script && echo create partition primary >> imDiskpart.script && echo assign letter=I >> imDiskpart.script&& echo exit >> imDiskpart.script && diskpart /s imDiskpart.script && format I: /FS:NTFS /V:local /Q /y"
online_disk_cmd = "echo select disk %s > imDiskpart.script && echo online disk >> imDiskpart.script && echo attr disk clear readonly >> imDiskpart.script && echo exit >> imDiskpart.script && diskpart /s imDiskpart.script"
guest_result_file = "C:\\fio_result"
fio_cmd = 'cmd /c C:\fio-2.0.15-x64\fio.exe --rw=%s --bs=%s --iodepth=%s --runtime=1m --direct=1 --filename=I\:\%s --name=job1 --ioengine=windowsaio --thread --group_reporting --numjobs=%s --size=512MB --time_based --output="C:\\fio_result"'
variants:
- file_system_block:
image_size_disk1 = 40G
force_create_image_disk1 = yes
remove_image_disk1 = yes
format = True
variants:
- localfs:
#You can specify your own directory which data disk is in. In our actual test, the /mnt is mounted on a ssd.
image_name_disk1 = /mnt/storage2
Linux:
vhost_nic1 =
iothreads = iothread0
virtio_blk, virtio_scsi:
blk_extra_params_image1 = "iothread=${iothreads}"
- nfs_block:
image_name_disk1 = images/storage2
- raw_disk:
image_raw_device_disk1 = yes
vhost_nic1 =
variants:
- fusion-io:
#Pls specify your own fusion-io ssd in the host.
image_name_disk1 = /dev/fioa
Linux:
fio_cmd = "i=`/bin/ls /dev/[vs]db` && fio --rw=%s --bs=%s --iodepth=%s --runtime=1m --direct=1 --filename=$i --name=job1 --ioengine=libaio --thread --group_reporting --numjobs=%s --time_based --output=/tmp/fio_result &> /dev/null"
Windows:
fio_cmd = 'cmd /c C:\fio-2.0.15-x64\fio.exe --rw=%s --bs=%s --iodepth=%s --runtime=1m --direct=1 --filename=\\.\PHYSICALDRIVE1 --name=job1 --ioengine=windowsaio --thread --group_reporting --numjobs=%s --size=512MB --time_based --output="C:\\fio_result"'
variants:
- single_disk:
images += " disk1"
num_disk = "1"
import os
import re
import time
import threading
import logging
from autotest.client import utils
from avocado.utils import process
from avocado.core import exceptions
from virttest import utils_misc, utils_test
from virttest import data_dir
def format_result(result, base="12", fbase="2"):
"""
Format the result to a fixed length string.
:param result: result need to convert
:param base: the length of converted string
:param fbase: the decimal digit for float
"""
if isinstance(result, str):
value = "%" + base + "s"
elif isinstance(result, int):
value = "%" + base + "d"
elif isinstance(result, float):
value = "%" + base + "." + fbase + "f"
return value % result
def check_disk_status(session, timeout, num):
"""
Output disk info including disk status
:param session: VM session
:param timeout: Timeout in seconds
:param num: The number of data disks
"""
disk_status_cmd = "echo list disk > cmd && echo exit >>"
disk_status_cmd += " cmd && diskpart /s cmd"
disks = []
end_time = time.time() + timeout
while time.time() < end_time:
disks_str = session.cmd_output_safe(disk_status_cmd)
logging.info("disks_str is %s" % disks_str)
disks = re.findall("Disk %s.*\n" % num, disks_str)
if not disks:
continue
return disks
def get_version(session, result_file, kvm_ver_chk_cmd, guest_ver_cmd, type, driver_format, timeout):
"""
collect qemu, kernel and driver version info and write them info results file
:param session: VM session
:param results_file: save fio results, host info and other info
:param guest_ver_cmd: command of getting guest kernel or virtio_win driver version
:param type: guest type
:param driver_format: driver format
:param timeout: Timeout in seconds
"""
kvm_ver = utils.system_output(kvm_ver_chk_cmd)
host_ver = os.uname()[2]
result_file.write("### kvm-userspace-ver : %s\n" % kvm_ver)
result_file.write("### kvm_version : %s\n" % host_ver)
if driver_format != "ide":
result = session.cmd_output(guest_ver_cmd, timeout)
if type == "windows":
guest_ver = re.findall(".*?(\d{2}\.\d{2}\.\d{3}\.\d{4}).*?", result)
result_file.write("### guest-kernel-ver :Microsoft Windows [Version %s]\n" % guest_ver[0])
else:
result_file.write("### guest-kernel-ver :%s" % result)
else:
result_file.write("### guest-kernel-ver : Microsoft Windows [Version ide driver format]\n")
def run(test, params, env):
"""
Block performance test with fio
Steps:
1) boot up guest with one data disk on specified backend and pin qemu-kvm process to the last numa node on host
2) pin guest vcpu and vhost threads to cpus of last numa node repectively
3) format data disk and run fio in guest
4) collect fio results and host info
:param test: QEMU test object
:param params: Dictionary with the test parameters
:param env: Dictionary with test environment
"""
def fio_thread(session, run_cmd, cmd_timeout):
"""
run fio command in guest
:param session: VM session
:param run_cmd: fio command
:param cmd_timeout: Timeout in seconds
"""
session.cmd_status(run_cmd, cmd_timeout)
def _pin_vm_threads(vm, node):
"""
pin guest vcpu and vhost threads to cpus of a numa node repectively
:param vm: VM object
:param node: which numa node to pin
"""
if node:
if not isinstance(node, utils_misc.NumaNode):
node = utils_misc.NumaNode(int(node))
utils_test.qemu.pin_vm_threads(vm, node)
# login virtual machine
vm = env.get_vm(params["main_vm"])
vm.verify_alive()
login_timeout = int(params.get("login_timeout", 360))
session = vm.wait_for_login(timeout=login_timeout)
process.system_output("numactl --hardware")
process.system_output("numactl --show")
_pin_vm_threads(vm, params.get("numa_node"))
# get parameter from dictionary
fio_cmd = params["fio_cmd"]
rw = params["rw"]
block_size = params["block_size"]
iodepth = params["iodepth"]
threads = params["threads"]
cmd_timeout = int(params.get("cmd_timeout", 1200))
order_list = params["order_list"]
driver_format = params.get("drive_format")
kvm_ver_chk_cmd = params.get("kvm_ver_chk_cmd")
guest_ver_cmd = params["guest_ver_cmd"]
pattern = params["pattern"]
pre_cmd = params["pre_cmd"]
format = params.get("format")
os_type = params.get("os_type", "linux")
drop_cache = params.get("drop_cache")
num_disk = params.get("num_disk")
result_path = utils_misc.get_path(test.resultsdir,
"fio_result.RHS")
result_file = open(result_path, "w")
# scratch host and windows guest version info
get_version(session, result_file, kvm_ver_chk_cmd, guest_ver_cmd, os_type,
driver_format, cmd_timeout)
# online disk
if os_type == "windows":
for num in range(1, int(num_disk) + 1):
disks = check_disk_status(session, cmd_timeout, num)
diskstatus = re.findall("Disk\s+\d+\s+(\w+).*?\s+\d+", disks[0])[0]
if diskstatus == "Offline":
online_disk_cmd = params.get("online_disk_cmd")
online_disk_run = online_disk_cmd % num
(s, o) = session.cmd_status_output(online_disk_run,
timeout=cmd_timeout)
if s:
raise exceptions.TestFail("Failed to online disk: %s" % o)
# format disk
if format:
session.cmd(pre_cmd, cmd_timeout)
# get order_list
order_line = ""
for order in order_list.split():
order_line += "%s|" % format_result(order)
# get result tested by each scenario
for io_pattern in rw.split():
result_file.write("Category:%s\n" % io_pattern)
result_file.write("%s\n" % order_line.rstrip("|"))
for bs in block_size.split():
for io_depth in iodepth.split():
for numjobs in threads.split():
line = ""
line += "%s|" % format_result(bs[:-1])
line += "%s|" % format_result(io_depth)
line += "%s|" % format_result(numjobs)
if format == "True":
file_name = io_pattern + "_" + bs + "_" + io_depth
run_cmd = fio_cmd % (io_pattern, bs, io_depth, file_name, numjobs)
else:
run_cmd = fio_cmd % (io_pattern, bs, io_depth, numjobs)
logging.info("run_cmd is: %s" % run_cmd)
if os_type == "linux":
(s, o) = session.cmd_status_output(drop_cache,
timeout=cmd_timeout)
if s:
raise exceptions.TestFail("Failed to free memory: %s" % o)
cpu_file = os.path.join(data_dir.get_tmp_dir(), "cpus")
io_exits_b = int(process.system_output("cat /sys/kernel/debug/kvm/exits"))
fio_t = threading.Thread(target=fio_thread, args=(session, run_cmd, cmd_timeout))
fio_t.start()
process.system_output("mpstat 1 60 > %s" % cpu_file, shell=True)
fio_t.join()
io_exits_a = int(process.system_output("cat /sys/kernel/debug/kvm/exits"))
vm.copy_files_from(params.get("guest_result_file"), data_dir.get_tmp_dir())
fio_result_file = os.path.join(data_dir.get_tmp_dir(), "fio_result")
o = process.system_output("egrep '(read|write)' %s" % fio_result_file)
results = re.findall(pattern, o)
o = process.system_output("egrep 'lat' %s" % fio_result_file)
laten = re.findall("\s{5}lat\s\((\wsec)\).*?avg=[\s]?(\d+(?:[\.][\d]+)?).*?", o)
bw = float(utils_misc.normalize_data_size(results[0][0]))
iops = int(results[0][1])
if os_type == "linux":
o = process.system_output("egrep 'util' %s" % fio_result_file)
util = float(re.findall(".*?util=(\d+(?:[\.][\d]+))%", o)[0])
lat = float(laten[0][1]) / 1000 if laten[0][0] == "usec" else float(laten[0][1])
if re.findall("rw", io_pattern):
bw = bw + float(utils_misc.normalize_data_size(results[1][0]))
iops = iops + int(results[1][1])
lat1 = float(laten[1][1]) / 1000 if laten[1][0] == "usec" else float(laten[1][1])
lat = lat + lat1
ret = process.system_output("tail -n 1 %s" % cpu_file)
idle = float(ret.split()[-1])
iowait = float(ret.split()[5])
cpu = 100 - idle - iowait
normal = bw / cpu
io_exits = io_exits_a - io_exits_b
for result in bw, iops, lat, cpu, normal:
line += "%s|" % format_result(result)
if os_type == "windows":
line += "%s" % format_result(io_exits)
if os_type == "linux":
line += "%s|" % format_result(io_exits)
line += "%s" % format_result(util)
result_file.write("%s\n" % line)
session.close()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册