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).
This commit is contained in:
John Lindgren 2018-12-07 20:06:18 -05:00
parent d5c1a4b41a
commit fb5d107581

View File

@ -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