Compare commits

...
6 Commits
Author SHA1 Message Date
josh 5beddd63ac bundle update 2019-07-02 19:46:30 -04:00
josh 4967f89a76 fix inconsistent type handling in VarSet#expand_varref - #73 2019-04-14 14:10:13 -04:00
josh 7cc68b2ce1 Remove Cache dirty-tracking
It really wasn't necessary since Cache#write is not called often.
2019-04-04 15:20:35 -04:00
josh be058dd18b avoid mkdir() race conditions - close #75 2018-12-11 22:13:33 -05:00
josh ad703a5c84 call Bundler.setup in build_tests_spec.rb 2018-12-09 21:20:16 -05:00
John Lindgren fb5d107581 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).
2018-12-07 20:06:18 -05:00
7 changed files with 67 additions and 52 deletions

No files matched your search

+17 -17
View File
@@ -8,29 +8,29 @@ GEM
remote: https://rubygems.org/
specs:
diff-lcs (1.3)
docile (1.1.5)
json (2.1.0)
rake (12.3.1)
rdoc (5.1.0)
rspec (3.6.0)
rspec-core (~> 3.6.0)
rspec-expectations (~> 3.6.0)
rspec-mocks (~> 3.6.0)
rspec-core (3.6.0)
rspec-support (~> 3.6.0)
rspec-expectations (3.6.0)
docile (1.3.2)
json (2.2.0)
rake (12.3.2)
rdoc (6.1.1)
rspec (3.8.0)
rspec-core (~> 3.8.0)
rspec-expectations (~> 3.8.0)
rspec-mocks (~> 3.8.0)
rspec-core (3.8.2)
rspec-support (~> 3.8.0)
rspec-expectations (3.8.4)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.6.0)
rspec-mocks (3.6.0)
rspec-support (~> 3.8.0)
rspec-mocks (3.8.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.6.0)
rspec-support (3.6.0)
rspec-support (~> 3.8.0)
rspec-support (3.8.2)
simplecov (0.15.0)
docile (~> 1.1.0)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.2)
yard (0.9.12)
yard (0.9.20)
PLATFORMS
ruby
@@ -45,4 +45,4 @@ DEPENDENCIES
yard
BUNDLED WITH
1.16.6
1.17.3
+5 -11
View File
@@ -85,17 +85,14 @@ module Rscons
@lookup_checksums = {}
end
# Write the cache to disk to be loaded next time.
# Write the cache to disk.
#
# @return [void]
def write
if @dirty || (@cache["version"] != VERSION)
@cache["version"] = VERSION
File.open(CACHE_FILE, "w") do |fh|
fh.puts(JSON.dump(@cache))
end
@cache["version"] = VERSION
File.open(CACHE_FILE, "w") do |fh|
fh.puts(JSON.dump(@cache))
end
@dirty = false
end
# Check if target(s) are up to date.
@@ -249,7 +246,6 @@ module Rscons
}
end,
}
@dirty = true
end
end
@@ -272,9 +268,8 @@ module Rscons
next if parts[i] == ""
subpath = File.join(*parts[0, i + 1])
unless File.exists?(subpath)
FileUtils.mkdir(subpath)
FileUtils.mkdir_p(subpath)
@cache["directories"][subpath] = true
@dirty = true
end
end
end
@@ -315,7 +310,6 @@ module Rscons
@cache["targets"] ||= {}
@cache["directories"] ||= {}
@lookup_checksums = {}
@dirty = false
end
# Return a file's checksum, or the previously calculated checksum for
+23 -17
View File
@@ -94,36 +94,42 @@ module Rscons
# @return [nil, String, Array, Symbol, TrueClass, FalseClass]
# Expanded value with "$!{var}" variable references replaced.
def expand_varref(varref, lambda_args)
if varref.is_a?(String)
case varref
when Symbol, true, false, nil
varref
when 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)
if varval.is_a?(String) or varval.nil?
expand_varref("#{prefix}#{varval}#{suffix}", lambda_args)
elsif varval.is_a?(Array)
varval.map {|vv| expand_varref("#{prefix}#{vv}#{suffix}", lambda_args)}.flatten
# suffix needs no expansion since the regex matches the last occurence
case varval
when Symbol, true, false, nil, String
if prefix.is_a?(Array)
prefix.map {|p| "#{p}#{varval}#{suffix}"}
else
"#{prefix}#{varval}#{suffix}"
end
when Array
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})"
raise "Unknown construction variable type: #{varval.class} (from #{varname.inspect} => #{self[varname].inspect})"
end
else
varref
end
elsif varref.is_a?(Array)
when Array
varref.map do |ent|
expand_varref(ent, lambda_args)
end.flatten
elsif varref.is_a?(Proc)
when Proc
expand_varref(varref[*lambda_args], lambda_args)
elsif varref.nil?
nil
elsif varref.is_a?(Symbol)
varref
elsif varref.is_a?(TrueClass)
varref
elsif varref.is_a?(FalseClass)
varref
else
raise "Unknown varref type: #{varref.class} (#{varref.inspect})"
raise "Unknown construction variable type: #{varref.class} (#{varref.inspect})"
end
end
+2
View File
@@ -74,6 +74,8 @@ describe Rscons do
command_name = "#{command_prefix}#{@statics[:build_test_id]}"
File.open("_simplecov_setup.rb", "w") do |fh|
fh.puts <<EOF
require "bundler"
Bundler.setup
require "simplecov"
class MyFormatter
def format(*args)
+4 -4
View File
@@ -26,13 +26,13 @@ module Rscons
cache = build_from(_cache)
expect(File).to receive(:exists?).with("one").and_return(true)
expect(File).to receive(:exists?).with("one/two").and_return(false)
expect(FileUtils).to receive(:mkdir).with("one/two")
expect(FileUtils).to receive(:mkdir_p).with("one/two")
expect(File).to receive(:exists?).with("one/two/three").and_return(false)
expect(FileUtils).to receive(:mkdir).with("one/two/three")
expect(FileUtils).to receive(:mkdir_p).with("one/two/three")
expect(File).to receive(:exists?).with("one").and_return(true)
expect(File).to receive(:exists?).with("one/two").and_return(true)
expect(File).to receive(:exists?).with("one/two/four").and_return(false)
expect(FileUtils).to receive(:mkdir).with("one/two/four")
expect(FileUtils).to receive(:mkdir_p).with("one/two/four")
cache.mkdir_p("one/two/three")
cache.mkdir_p("one\\two\\four")
expect(cache.directories).to eq ["one/two", "one/two/three", "one/two/four"]
@@ -43,7 +43,7 @@ module Rscons
cache = build_from(_cache)
expect(File).to receive(:exists?).with("/one").and_return(true)
expect(File).to receive(:exists?).with("/one/two").and_return(false)
expect(FileUtils).to receive(:mkdir).with("/one/two")
expect(FileUtils).to receive(:mkdir_p).with("/one/two")
cache.mkdir_p("/one/two")
expect(cache.directories).to eq ["/one/two"]
end
+1 -1
View File
@@ -184,7 +184,7 @@ module Rscons
env["foo"] = {}
expect(env.expand_varref(["-p${path}", "${flags}"])).to eq ["-pdir1", "-pdir2", "-x", "-y", "-z"]
expect(env.expand_varref("foo")).to eq "foo"
expect {env.expand_varref("${foo}")}.to raise_error /Unknown.varref.type/
expect {env.expand_varref("${foo}")}.to raise_error /Unknown.construction.variable.type/
expect(env.expand_varref("${specialflag}")).to eq "-z"
expect(env.expand_varref("${path}")).to eq ["dir1", "dir2"]
end
+15 -2
View File
@@ -166,13 +166,26 @@ module Rscons
expect(v.expand_varref(false, :lambda_args)).to eq(false)
end
it "raises an error when given an invalid argument" do
expect { v.expand_varref({a: :b}, :lambda_args) }.to raise_error /Unknown varref type: Hash/
expect { v.expand_varref({a: :b}, :lambda_args) }.to raise_error /Unknown construction variable type: Hash/
end
it "raises an error when an expanded variable is an unexpected type" do
expect(v).to receive(:[]).at_least(1).times.with("bad").and_return("bad_val")
expect(v).to receive(:expand_varref).with("bad_val", :lambda_args).and_return({a: :b})
expect(v).to receive(:expand_varref).and_call_original
expect { v.expand_varref("${bad}", :lambda_args) }.to raise_error /I do not know how to expand a variable reference to a Hash/
expect { v.expand_varref("${bad}", :lambda_args) }.to raise_error /Unknown construction variable type: Hash/
end
it "expands symbols within a string outside an array" do
v['var'] = :a_symbol
expect(v.expand_varref("this is ${var}", :lambda_args)).to eq "this is a_symbol"
end
it "expands booleans within a string outside an array" do
v['var'] = false
expect(v.expand_varref("this is ${var}", :lambda_args)).to eq "this is false"
end
it "expands symbols and booleans in an array" do
v['var'] = [:a_symbol, false]
expanded = v.expand_varref("this is ${var}", :lambda_args)
expect(expanded).to eq(["this is a_symbol", "this is false"])
end
end