1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
#!/usr/bin/env python3
"""
Performance tests using fsck.ext2 on a test file.
It can be tuned with the following environment variables:
- TEST_FILE: The name of the file used for testing. By default, ".test_fs".
- TEST_FILE_SIZE_MB: The size of the test file, in megabytes. Only used if
the file doesn't exist. Default: 10.
- VERBOSE: Show verbose output (from 0 to 2). Default: 0.
- LD_LIBRARY_PATH: Library path to pass on to the subcommands.
Default: <directory of this file>/../libfiu/, which is usually the one
containing the current build.
"""
import os
import sys
import subprocess
import time
test_file = os.environ.get("TEST_FILE", ".test_fs")
test_file_size = int(os.environ.get("TEST_FILE_SIZE_MB", 10))
ld_library_path = os.environ.get(
"LD_LIBRARY_PATH",
os.path.abspath(
os.path.abspath(os.path.dirname(sys.argv[0])) + "/../libfiu/"
),
)
verbose = int(os.environ.get("VERBOSE", 0))
dev_null = open("/dev/null", "w")
def run_child(name, args, stdout=dev_null, stderr=dev_null):
"""Runs the subprocess, returns the Popen object."""
env = dict(os.environ)
env["LD_LIBRARY_PATH"] = ld_library_path
if verbose and stdout == stderr == dev_null:
stdout = stderr = None
child = subprocess.Popen(args, env=env, stdout=stdout, stderr=stderr)
return child
def run_and_time(name, args):
"""Run the given arguments, print the times."""
start = time.time()
child = run_child(name, args)
_, status, rusage = os.wait4(child.pid, 0)
end = time.time()
if verbose == 2:
print("Ran %s -> %d" % (args, status))
if status != 0:
print("Error running %s: %s" % (args[0], status))
raise RuntimeError
print(
"%-10s u:%.3f s:%.3f r:%.3f"
% (name, rusage.ru_utime, rusage.ru_stime, end - start)
)
def run_fsck(name, fiu_args):
"""Runs an fsck with the given fiu arguments."""
child = run_child(
name,
["fiu-run", "-x"]
+ fiu_args
+ "fsck.ext2 -n -t -f".split()
+ [test_file],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
stdout, stderr = child.communicate()
if child.returncode != 0:
print("Error running fsck: %s" % child.returncode)
raise RuntimeError
# Find the times reported by fsck.
# Not very robust, but useful as it measures the real program time run,
# and not the startup overhead.
# The line looks like:
# Memory used: 560k/0k (387k/174k), time: 2.18/ 2.17/ 0.00
user_time = sys_time = real_time = -1
for l in stdout.split("\n"):
if not l.startswith("Memory used"):
continue
times = l.split(":")[-1].split("/")
times = [s.strip() for s in times]
if len(times) != 3:
continue
real_time = float(times[0])
user_time = float(times[1])
sys_time = float(times[2])
break
print(
"%-10s u:%.3f s:%.3f r:%.3f" % (name, user_time, sys_time, real_time)
)
def check_test_file():
if os.path.exists(test_file):
return
with open(test_file, "w") as fd:
fd.truncate(test_file_size * 1024 * 1024)
retcode = subprocess.call(
["mkfs.ext2", "-F", test_file], stdout=open("/dev/null", "w")
)
if retcode != 0:
print("Error running mkfs.ext2:", retcode)
return
if __name__ == "__main__":
check_test_file()
run_and_time("base", "fsck.ext2 -n -f".split() + [test_file])
# 1 all-matching wildcard.
run_fsck("w1", ["-c", "enable_random name=*,probability=0"])
# 1k final failure points, no matches.
args = []
for i in range(1000):
args += ["-c", "enable_random name=none/%d,probability=0" % i]
run_fsck("f1k", args)
# 1k wildcard failure points, no matches.
args = []
for i in range(1000):
args += ["-c", "enable_random name=none/%d/*,probability=0" % i]
run_fsck("w1k", args)
# 1k wildcarded failure points, and 1 match.
args = []
for i in range(1000):
args += ["-c", "enable_random name=none/%d/*,probability=0" % i]
args += ["-c", "enable_random name=*,probability=0"]
run_fsck("w1k+1", args)
# 1k final failure points, *all* matches.
args = []
for i in range(1000):
args += ["-c", "enable_random name=*,probability=0"]
run_fsck("m1k", args)
|