author | Alberto Bertogli
<albertito@blitiri.com.ar> 2013-10-29 02:01:01 UTC |
committer | Alberto Bertogli
<albertito@blitiri.com.ar> 2013-10-29 02:12:13 UTC |
parent | 5c20f63dba8dae4c46a43af6ff40f0103d653718 |
tests/perf-fsck.py | +148 | -0 |
diff --git a/tests/perf-fsck.py b/tests/perf-fsck.py new file mode 100644 index 0000000..8d367b9 --- /dev/null +++ b/tests/perf-fsck.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python + +""" +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)