From 19819cffc065dcf54c95be09c65e4e54ecc59270 Mon Sep 17 00:00:00 2001 From: stevenknight Date: Tue, 8 Mar 2005 18:05:41 +0000 Subject: [PATCH] Speed up string expansion. Cache find_file() results in the Memoizer. git-svn-id: http://scons.tigris.org/svn/scons/trunk@1249 fdb21ef1-2011-0410-befe-b5e4ea1792b1 --- bin/bench.py | 129 ++++++++++++++++++++++++++++++++++++ src/engine/SCons/Node/FS.py | 1 + src/engine/SCons/Util.py | 16 ++--- 3 files changed, 136 insertions(+), 10 deletions(-) create mode 100644 bin/bench.py diff --git a/bin/bench.py b/bin/bench.py new file mode 100644 index 00000000..7d9e2ba0 --- /dev/null +++ b/bin/bench.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python +# +# A script for timing snippets of Python code. + +import time + +Now = time.time +#Now = time.clock # better on Windows, some UNIX/Linux systems + +# How many times each snippet of code will be run by the functions +# to gather the time (the "inner loop"). + +Iterations = 10000 + +# How many times we'll run each function to collect its aggregate time +# and try to average out timing differences induced by system performance +# (the "outer loop"). + +Runs = 10 + +# The functions containing the code snippets to test and compare. +# This script will test any function whose name begins with the string +# "Func" and assumes that they all get passed the same arguments. +# Each function should put its snippet within a block: +# +# for i in IterationList: +# +# So that (as much as possible) we're testing just the code itself, +# not Python function call overhead. + +def Func1(var, gvars, lvars): + for i in IterationList: + try: + x = lvars[var] + except KeyError: + try: + x = gvars[var] + except KeyError: + x = '' + +def Func2(var, gvars, lvars): + for i in IterationList: + if lvars.has_key(var): + x = lvars[var] + else: + try: + x = gvars[var] + except KeyError: + x = '' + +def Func3(var, gvars, lvars): + for i in IterationList: + if lvars.has_key(var): + x = lvars[var] + elif gvars.has_key(var): + x = gvars[var] + else: + x = '' + +def Func4(var, gvars, lvars): + for i in IterationList: + try: + x = eval(var, gvars, lvars) + except NameError: + x = '' + +# Data to pass to the functions on each run. Each entry is a +# three-element tuple: +# +# ( +# "Label to print describing this data run", +# ('positional', 'arguments'), +# {'keyword' : 'arguments'}, +# ), + +Data = [ + ( + "Neither in gvars or lvars", + ('x', {}, {}), + {}, + ), + ( + "Missing from lvars, found in gvars", + ('x', {'x':1}, {}), + {}, + ), + ( + "Found in lvars", + ('x', {'x':1}, {'x':2}), + {}, + ), +] + + + +IterationList = [None] + +def timer(func, *args, **kw): + global IterationList + IterationList = [None] * Iterations + results = [] + for i in range(Runs): + start = Now() + func(*args, **kw) + finish = Now() + results.append((finish - start) / Iterations) + return results + +def display(label, results): + print ' ' + label + ':' + print ' ', + for r in results: + print "%.3f" % (r * 1e6), + print + +def display(label, results): + total = reduce(lambda x, y: x+y, results, 0.0) + print " %8.3f" % ((total * 1e6) / len(results)), ':', label + +func_names = filter(lambda x: x.startswith('Func'), locals().keys()) +func_names.sort() + +for f in func_names: + func = locals()[f] + print f + ':' + + for label, args, kw in Data: + r = apply(timer, (func,)+args, kw) + display(label, r) diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index 9dfd355b..336ba1f0 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -1892,6 +1892,7 @@ def find_file(filename, paths, verbose=None): Only the first file found is returned, and none is returned if no file is found. + __cacheable__ """ if verbose: if not SCons.Util.is_String(verbose): diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 2ca487f2..e76087d8 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -582,15 +582,6 @@ def scons_subst(strSubst, env, mode=SUBST_RAW, target=None, source=None, gvars={ self.conv = conv self.gvars = gvars - def expand_var_once(self, var, lvars): - try: - return lvars[var] - except KeyError: - try: - return self.gvars[var] - except KeyError: - return '' - def expand(self, s, lvars): """Expand a single "token" as necessary, returning an appropriate string containing the expansion. @@ -629,7 +620,12 @@ def scons_subst(strSubst, env, mode=SUBST_RAW, target=None, source=None, gvars={ else: raise SCons.Errors.UserError, "Syntax error `%s' trying to evaluate `%s'" % (e,s) else: - s = self.expand_var_once(key, lvars) + if lvars.has_key(key): + s = lvars[key] + elif self.gvars.has_key(key): + s = self.gvars[key] + else: + return '' # Before re-expanding the result, handle # recursive expansion by copying the local -- 2.26.2