166 lines
4.7 KiB
Python
166 lines
4.7 KiB
Python
# python3
|
|
# Copyright 2019 Google LLC
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
"""File I/O tests."""
|
|
|
|
import os
|
|
|
|
from benchmarks import suites
|
|
from benchmarks.harness import machine
|
|
from benchmarks.suites import helpers
|
|
from benchmarks.workloads import fio
|
|
|
|
|
|
# pylint: disable=too-many-arguments
|
|
# pylint: disable=too-many-locals
|
|
def run_fio(target: machine.Machine,
|
|
test: str,
|
|
ioengine: str = "sync",
|
|
size: int = 1024 * 1024 * 1024,
|
|
iodepth: int = 4,
|
|
blocksize: int = 1024 * 1024,
|
|
time: int = -1,
|
|
mount_dir: str = "",
|
|
filename: str = "file.dat",
|
|
tmpfs: bool = False,
|
|
ramp_time: int = 0,
|
|
**kwargs) -> str:
|
|
"""FIO benchmarks.
|
|
|
|
For more on fio see:
|
|
https://media.readthedocs.org/pdf/fio/latest/fio.pdf
|
|
|
|
Args:
|
|
target: A machine object.
|
|
test: The test to run (read, write, randread, randwrite, etc.)
|
|
ioengine: The engine for I/O.
|
|
size: The size of the generated file in bytes (if an integer) or 5g, 16k,
|
|
etc.
|
|
iodepth: The I/O for certain engines.
|
|
blocksize: The blocksize for reads and writes in bytes (if an integer) or
|
|
4k, etc.
|
|
time: If test is time based, how long to run in seconds.
|
|
mount_dir: The absolute path on the host to mount a bind mount.
|
|
filename: The name of the file to creat inside container. For a path of
|
|
/dir/dir/file, the script setup a volume like 'docker run -v
|
|
mount_dir:/dir/dir fio' and fio will create (and delete) the file
|
|
/dir/dir/file. If tmpfs is set, this /dir/dir will be a tmpfs.
|
|
tmpfs: If true, mount on tmpfs.
|
|
ramp_time: The time to run before recording statistics
|
|
**kwargs: Additional container options.
|
|
|
|
Returns:
|
|
The output of fio as a string.
|
|
"""
|
|
# Pull the image before dropping caches.
|
|
image = target.pull("fio")
|
|
|
|
if not mount_dir:
|
|
stdout, _ = target.run("pwd")
|
|
mount_dir = stdout.rstrip()
|
|
|
|
# Setup the volumes.
|
|
volumes = {mount_dir: {"bind": "/disk", "mode": "rw"}} if not tmpfs else None
|
|
tmpfs = {"/disk": ""} if tmpfs else None
|
|
|
|
# Construct a file in the volume.
|
|
filepath = os.path.join("/disk", filename)
|
|
|
|
# If we are running a read test, us fio to write a file and then flush file
|
|
# data from memory.
|
|
if "read" in test:
|
|
target.container(
|
|
image, volumes=volumes, tmpfs=tmpfs, **kwargs).run(
|
|
test="write",
|
|
ioengine="sync",
|
|
size=size,
|
|
iodepth=iodepth,
|
|
blocksize=blocksize,
|
|
path=filepath)
|
|
helpers.drop_caches(target)
|
|
|
|
# Run the test.
|
|
time_str = "--time_base --runtime={time}".format(
|
|
time=time) if int(time) > 0 else ""
|
|
res = target.container(
|
|
image, volumes=volumes, tmpfs=tmpfs, **kwargs).run(
|
|
test=test,
|
|
ioengine=ioengine,
|
|
size=size,
|
|
iodepth=iodepth,
|
|
blocksize=blocksize,
|
|
time=time_str,
|
|
path=filepath,
|
|
ramp_time=ramp_time)
|
|
|
|
target.run(
|
|
"rm {path}".format(path=os.path.join(mount_dir.rstrip(), filename)))
|
|
|
|
return res
|
|
|
|
|
|
@suites.benchmark(metrics=[fio.read_bandwidth, fio.read_io_ops], machines=1)
|
|
def read(*args, **kwargs):
|
|
"""Read test.
|
|
|
|
Args:
|
|
*args: None.
|
|
**kwargs: Additional container options.
|
|
|
|
Returns:
|
|
The output of fio.
|
|
"""
|
|
return run_fio(*args, test="read", **kwargs)
|
|
|
|
|
|
@suites.benchmark(metrics=[fio.read_bandwidth, fio.read_io_ops], machines=1)
|
|
def randread(*args, **kwargs):
|
|
"""Random read test.
|
|
|
|
Args:
|
|
*args: None.
|
|
**kwargs: Additional container options.
|
|
|
|
Returns:
|
|
The output of fio.
|
|
"""
|
|
return run_fio(*args, test="randread", **kwargs)
|
|
|
|
|
|
@suites.benchmark(metrics=[fio.write_bandwidth, fio.write_io_ops], machines=1)
|
|
def write(*args, **kwargs):
|
|
"""Write test.
|
|
|
|
Args:
|
|
*args: None.
|
|
**kwargs: Additional container options.
|
|
|
|
Returns:
|
|
The output of fio.
|
|
"""
|
|
return run_fio(*args, test="write", **kwargs)
|
|
|
|
|
|
@suites.benchmark(metrics=[fio.write_bandwidth, fio.write_io_ops], machines=1)
|
|
def randwrite(*args, **kwargs):
|
|
"""Random write test.
|
|
|
|
Args:
|
|
*args: None.
|
|
**kwargs: Additional container options.
|
|
|
|
Returns:
|
|
The output of fio.
|
|
"""
|
|
return run_fio(*args, test="randwrite", **kwargs)
|