diff options
author | Steven Knight <knight@baldmt.com> | 2009-11-19 08:03:26 (GMT) |
---|---|---|
committer | Steven Knight <knight@baldmt.com> | 2009-11-19 08:03:26 (GMT) |
commit | 57bf294eaae19922e6e39e5c8e9138112b088641 (patch) | |
tree | ce6a93f58cf7d94d174279509431ccb8d51810d7 /QMTest | |
parent | fa7db45e10075bb0010e8134503e7c93ddbb9e30 (diff) | |
download | SCons-57bf294eaae19922e6e39e5c8e9138112b088641.zip SCons-57bf294eaae19922e6e39e5c8e9138112b088641.tar.gz SCons-57bf294eaae19922e6e39e5c8e9138112b088641.tar.bz2 |
Capture initial infrastructure for working performance tests.
Diffstat (limited to 'QMTest')
-rw-r--r-- | QMTest/TestSCons.py | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/QMTest/TestSCons.py b/QMTest/TestSCons.py index a2bf8fc..1fed39a 100644 --- a/QMTest/TestSCons.py +++ b/QMTest/TestSCons.py @@ -18,6 +18,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os import re +import shutil import string import sys import time @@ -942,6 +943,129 @@ print py_ver else: alt_cpp_suffix = '.C' return alt_cpp_suffix + + +class TimeSCons(TestSCons): + """Class for timing SCons.""" + def __init__(self, *args, **kw): + """ + In addition to normal TestSCons.TestSCons intialization, + this enables verbose mode (which causes the command lines to + be displayed in the output) and copies the contents of the + directory containing the executing script to the temporary + working directory. + """ + if not kw.has_key('verbose'): + kw['verbose'] = True + TestSCons.__init__(self, *args, **kw) + + # TODO(sgk): better way to get the script dir than sys.argv[0] + test_dir = os.path.dirname(sys.argv[0]) + test_name = os.path.basename(test_dir) + + if not os.path.isabs(test_dir): + test_dir = os.path.join(self.orig_cwd, test_dir) + self.copy_timing_configuration(test_dir, self.workpath()) + + def main(self, *args, **kw): + """ + The main entry point for standard execution of timings. + + This method run SCons three times: + + Once with the --help option, to have it exit after just reading + the configuration. + + Once as a full build of all targets. + + Once again as a (presumably) null or up-to-date build of + all targets. + + The elapsed time to execute each build is printed after + it has finished. + """ + self.help(*args, **kw) + self.full(*args, **kw) + self.null(*args, **kw) + + def help(self, *args, **kw): + """ + Runs scons with the --help option. + + This serves as a way to isolate just the amount of time spent + reading up the configuration, since --help exits before any + "real work" is done. + """ + kw['options'] = kw.get('options', '') + ' --help' + self.run_build(*args, **kw) + sys.stdout.write(self.stdout()) + print "RESULT", self.elapsed_time() + + def full(self, *args, **kw): + """ + Runs a full build of SCons. + """ + self.run_build(*args, **kw) + sys.stdout.write(self.stdout()) + print "RESULT", self.elapsed_time() + + def null(self, *args, **kw): + """ + Runs an up-to-date null build of SCons. + """ + # TODO(sgk): allow the caller to specify the target (argument) + # that must be up-to-date. + self.up_to_date(arguments='.', **kw) + sys.stdout.write(self.stdout()) + print "RESULT", self.elapsed_time() + + def elapsed_time(self): + """ + Returns the elapsed time of the most recent command execution. + """ + return self.endTime - self.startTime + + def run_build(self, *args, **kw): + """ + Runs a single build command, capturing output in the specified file. + + Because this class is about timing SCons, we record the start + and end times of the elapsed execution, and also add the + --debug=memory and --debug=time options to have SCons report + its own memory and timing statistics. + """ + kw['options'] = kw.get('options', '') + ' --debug=memory --debug=time' + self.startTime = time.time() + try: + result = TestSCons.run(self, *args, **kw) + finally: + self.endTime = time.time() + return result + + def copy_timing_configuration(self, source_dir, dest_dir): + """ + Copies the timing configuration from the specified source_dir (the + directory in which the controlling script lives) to the specified + dest_dir (a temporary working directory). + + This ignores all files and directories that begin with the string + 'TimeSCons-', and all '.svn' subdirectories. + """ + for root, dirs, files in os.walk(source_dir): + if '.svn' in dirs: + dirs.remove('.svn') + dirs = [ d for d in dirs if not d.startswith('TimeSCons-') ] + files = [ f for f in files if not f.startswith('TimeSCons-') ] + for dirname in dirs: + source = os.path.join(root, dirname) + destination = source.replace(source_dir, dest_dir) + os.mkdir(destination) + if sys.platform != 'win32': + shutil.copystat(source, destination) + for filename in files: + source = os.path.join(root, filename) + destination = source.replace(source_dir, dest_dir) + shutil.copy2(source, destination) # In some environments, $AR will generate a warning message to stderr |