From a1efb1c1b3f853cde11e728cd0da41ccb055ce8b Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Fri, 7 Dec 2018 20:06:18 -0500 Subject: [PATCH] Reduce recursion of VarSet#expand_varref by expanding vars earlier. It's common for a build command to contain a reference like: ${INCPREFIX}${CPPPATH} Where ${INCPREFIX} is "-I" and ${CPPPATH} is an array of include paths. Without this change, Rscons expands ${INCPREFIX} (and then tries to expand "-I") repeatedly, once for each path. This change simply makes Rscons intelligent enough to expand ${INCPREFIX} only once, then join the expanded value to each path. In a mid-sized rake project, ruby-prof shows that the number of calls to expand_varref is reduced from ~80,000 to ~30,000., and the total CPU time spent in expand_varref is reduced by about 30%. In a larger project, the improvement in real build time is small but consistent enough to be measurable (~0.5 seconds off a total of ~20 seconds). --- lib/rscons/varset.rb | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/rscons/varset.rb b/lib/rscons/varset.rb index 2135c7a..f9183e7 100644 --- a/lib/rscons/varset.rb +++ b/lib/rscons/varset.rb @@ -97,11 +97,21 @@ module Rscons if varref.is_a?(String) if varref =~ /^(.*)\$\{([^}]+)\}(.*)$/ prefix, varname, suffix = $1, $2, $3 + prefix = expand_varref(prefix, lambda_args) unless prefix.empty? varval = expand_varref(self[varname], lambda_args) + # suffix needs no expansion since the regex matches the last occurence if varval.is_a?(String) or varval.nil? - expand_varref("#{prefix}#{varval}#{suffix}", lambda_args) + if prefix.is_a?(Array) + prefix.map {|p| "#{p}#{varval}#{suffix}"} + else + "#{prefix}#{varval}#{suffix}" + end elsif varval.is_a?(Array) - varval.map {|vv| expand_varref("#{prefix}#{vv}#{suffix}", lambda_args)}.flatten + if prefix.is_a?(Array) + varval.map {|vv| prefix.map {|p| "#{p}#{vv}#{suffix}"}}.flatten + else + varval.map {|vv| "#{prefix}#{vv}#{suffix}"} + end else raise "I do not know how to expand a variable reference to a #{varval.class.name} (from #{varname.inspect} => #{self[varname].inspect})" end