Permalink
Browse files

Significantly improve performance by eliminating use of StructHash in…

…ternally. The StructHash API is still available to user Buildfiles, where the method_missing is only hit a few times. Using it internally, on the other hand, resulted in huge amounts of hits to this relatively slow code path.
  • Loading branch information...
wycats committed Aug 20, 2010
1 parent 9d6ccfd commit 0cc2392f74a898c65092b7969f38df3f3685df9c
View
@@ -69,8 +69,8 @@ def self.env=(hash); @env = HashStruct.new(hash); end
def self.logger
return @logger unless @logger.nil?
- if env.logfile
- @logger = Logger.new env.logfile, 10, 1024000
+ if env[:logfile]
+ @logger = Logger.new env[:logfile], 10, 1024000
else
@logger = Logger.new $stderr
@@ -80,7 +80,7 @@ def self.logger
end
end
- @logger.level = (env.log_level == :debug) ? Logger::DEBUG : ((env.log_level == :info) ? Logger::INFO : Logger::WARN)
+ @logger.level = (env[:log_level] == :debug) ? Logger::DEBUG : ((env[:log_level] == :info) ? Logger::INFO : Logger::WARN)
return @logger
end
@@ -91,7 +91,7 @@ def self.logger
# compatibility reasons, :development and :debug are treated as being
# identical.
def self.build_mode
- ret = env.build_mode || :production
+ ret = env[:build_mode] || :production
ret = ret.to_sym unless ret.nil?
ret = :debug if ret == :development # backwards compatibility
ret
@@ -127,6 +127,13 @@ def self.load_project(path = nil, opts = {})
end
end
+ def self.yui_jar
+ @yui_jar ||= begin
+ yui_root = File.expand_path("../vendor/yui-compressor", __FILE__)
+ File.join(yui_root, 'yuicompressor-2.4.2.jar')
+ end
+ end
+
end # module SC
SC = SproutCore # alias
@@ -19,10 +19,10 @@ class Builder::Combine < Builder::Base
def build(dst_path)
lines = []
- entries = entry.ordered_entries || entry.source_entries
+ entries = entry[:ordered_entries] || entry[:source_entries]
- target_name = entry.target.target_name.to_s.sub(/^\//,'')
- if entry.top_level_lazy_instantiation && entry.combined
+ target_name = entry.target[:target_name].to_s.sub(/^\//,'')
+ if entry[:top_level_lazy_instantiation] && entry[:combined]
lines << ";
if ((typeof SC !== 'undefined') && SC && !SC.LAZY_INSTANTIATION) {
SC.LAZY_INSTANTIATION = {};
@@ -37,15 +37,15 @@ def build(dst_path)
end
entries.each do |entry|
- src_path = entry.stage!.staging_path
+ src_path = entry.stage![:staging_path]
next unless File.exist?(src_path)
- lines << "/* >>>>>>>>>> BEGIN #{entry.filename} */\n"
+ lines << "/* >>>>>>>>>> BEGIN #{entry[:filename]} */\n"
lines += readlines(src_path)
lines << "\n"
end
- if entry.top_level_lazy_instantiation && entry.combined
+ if entry[:top_level_lazy_instantiation] && entry[:combined]
lines << "
}
)
@@ -44,7 +44,7 @@ class Builder::Html < Builder::Base
# manifest owning the current entry
attr_reader :manifest
- def target_name; target.target_name.to_s.sub(/^\//,''); end
+ def target_name; target[:target_name].to_s.sub(/^\//,''); end
alias_method :bundle_name, :target_name # backwards compat
def config; target.config; end
@@ -59,29 +59,29 @@ def layout_entry
# from the layout property, which is a relative pathname.
def layout_path
entry = layout_entry
- entry.nil? ? nil : entry.staging_path
+ entry.nil? ? nil : entry[:staging_path]
end
def initialize(entry)
super(entry)
@target = @bundle = entry.manifest.target
- @filename = entry.filename
- @language = @entry.manifest.language
+ @filename = entry[:filename]
+ @language = @entry.manifest[:language]
@project = @library = @target.project
@manifest = entry.manifest
@renderer = nil
# set the current layout from the target's config.layout
- @layout = @target.config.layout || 'lib/index.rhtml'
+ @layout = @target.config[:layout] || 'lib/index.rhtml'
# find all entries -- use source_Entries + required if needed
- @entries = entry.source_entries.dup
+ @entries = entry[:source_entries].dup
if entry.include_required_targets?
@target.expand_required_targets.each do |target|
cur_manifest = target.manifest_for(@manifest.variation).build!
- cur_entry = cur_manifest.entry_for(entry.filename, :combined => true) || cur_manifest.entry_for(entry.filename, :hidden => true, :combined => true)
+ cur_entry = cur_manifest.entry_for(entry[:filename], :combined => true) || cur_manifest.entry_for(entry[:filename], :hidden => true, :combined => true)
next if cur_entry.nil?
- @entries += cur_entry.source_entries
+ @entries += cur_entry[:source_entries]
end
end
end
@@ -90,7 +90,7 @@ def initialize(entry)
# This method can be overridden by subclasses to provide specific
# config settings.
def expand_required_targets(target, opts = {})
- opts[:debug] = target.config.load_debug
+ opts[:debug] = target.config[:load_debug]
opts[:theme] = true
return target.expand_required_targets(opts)
end
@@ -112,9 +112,9 @@ def render
end
def build(dst_path)
- if CONFIG.html5_manifest
+ if CONFIG[:html5_manifest]
$to_html5_manifest << dst_path
- $to_html5_manifest_networks = CONFIG.html5_manifest_networks
+ $to_html5_manifest_networks = CONFIG[:html5_manifest_networks]
@content_for_html5_manifest = true
end
writelines dst_path, [self.render]
@@ -155,7 +155,7 @@ def compile(render_engine, input_path, content_for_key = nil)
input = File.read(input_path)
content_for content_for_key do
- _render_compiled_template( render_engine.compile(input) )
+ _render_compiled_template( render_engine.compile(input), input_path )
end
@render = old_renderer
@@ -188,15 +188,15 @@ def render_partial(entry)
def render_entry(entry)
@content_for_designer = '<script type="text/javascript">SC.suppressMain = YES;</script>' if $design_mode
entry.stage!
- entry.target.buildfile.invoke entry.render_task,
+ entry.target.buildfile.invoke entry[:render_task],
:entry => entry,
- :src_path => entry.staging_path,
+ :src_path => entry[:staging_path],
:context => self
end
# Renders a compiled template within this context
- def _render_compiled_template(compiled_template)
- self.instance_eval "def __render(); #{compiled_template}; end"
+ def _render_compiled_template(compiled_template, input_path="(compiled erb)")
+ self.instance_eval "def __render(); #{compiled_template}; end", input_path
begin
self.send(:__render) do |*names|
self.instance_variable_get("@content_for_#{names.first}")
@@ -18,10 +18,10 @@ class Builder::JavaScript < Builder::Base
def build(dst_path)
lines = []
- target_name = entry.target.target_name.to_s.sub(/^\//,'')
+ target_name = entry.target[:target_name].to_s.sub(/^\//,'')
- if entry.lazy_instantiation && entry.notify_onload
- lines << ";
+ if entry[:lazy_instantiation] && entry[:notify_onload]
+ lines << ";
if ((typeof SC !== 'undefined') && SC && !SC.LAZY_INSTANTIATION) {
SC.LAZY_INSTANTIATION = {};
}
@@ -34,14 +34,14 @@ def build(dst_path)
"
end
- lines << readlines(entry.source_path).map { |l| rewrite_inline_code(l) }
+ lines << readlines(entry[:source_path]).map { |l| rewrite_inline_code(l) }
# Try to load dependencies if we're not combining javascript.
- if entry.notify_onload
+ if entry[:notify_onload]
lines << "; if ((typeof SC !== 'undefined') && SC && SC.scriptDidLoad) SC.scriptDidLoad('#{target_name}');"
end
- if entry.lazy_instantiation && entry.notify_onload
+ if entry[:lazy_instantiation] && entry[:notify_onload]
lines << "
}
)
@@ -57,7 +57,7 @@ def build(dst_path)
# strings. -- You can name a string key beginning with "@@" and it will
# be removed.
def localized_strings?
- @lstrings ||= entry.localized? && entry.filename =~ /strings.js$/
+ @lstrings ||= entry.localized? && entry[:filename] =~ /strings.js$/
end
# Rewrites inline content for a single line
@@ -40,7 +40,7 @@ def build_css(dst_path)
FileUtils.copy(entry.source_path, dst_path)
else
FileUtils.mkdir_p(File.dirname(dst_path)) # make sure loc exists...
- filecompress = "java -jar " + yui_jar + " --charset utf-8 --line-break 0 --nomunge --preserve-semi --disable-optimizations " + entry.source_path + " -o \"" + dst_path + "\" 2>&1"
+ filecompress = "java -jar " + SC.yui_jar + " --charset utf-8 --line-break 0 --nomunge --preserve-semi --disable-optimizations " + entry.source_path + " -o \"" + dst_path + "\" 2>&1"
SC.logger.info 'Compressing CSS with YUI .... '+ dst_path
SC.logger.debug `#{filecompress}`
@@ -61,7 +61,7 @@ def build_javascript(dst_path)
FileUtils.copy(entry.source_path, dst_path)
else
FileUtils.mkdir_p(File.dirname(dst_path)) # make sure loc exists...
- filecompress = "java -jar " + yui_jar + " --charset utf-8 --line-break 80 " + entry.source_path + " -o \"" + dst_path + "\" 2>&1"
+ filecompress = "java -jar " + SC.yui_jar + " --charset utf-8 --line-break 80 " + entry.source_path + " -o \"" + dst_path + "\" 2>&1"
SC.logger.info 'Compressing with YUI: '+ dst_path + "..."
output = `#{filecompress}` # It'd be nice to just read STDERR, but
@@ -78,7 +78,7 @@ def build_javascript(dst_path)
def build_inline_javascript(dst_path)
SC.logger.info 'Compressing inline Javascript with YUI: ' + dst_path + "..."
FileUtils.mkdir_p(File.dirname(dst_path)) # make sure loc exists...
- filecompress = "java -jar " + yui_jar + " --charset utf-8 --line-break 80 " + entry.source_path + " -o \"" + dst_path + "\" 2>&1"
+ filecompress = "java -jar " + SC.yui_jar + " --charset utf-8 --line-break 80 " + entry.source_path + " -o \"" + dst_path + "\" 2>&1"
SC.logger.info 'Compressing with YUI: '+ dst_path + "..."
output = `#{filecompress}` # It'd be nice to just read STDERR, but
@@ -93,13 +93,6 @@ def build_inline_javascript(dst_path)
private
- def yui_jar
- @yui_jar ||= begin
- yui_root = File.expand_path("../../vendor/yui-compressor", __FILE__)
- File.join(yui_root, 'yuicompressor-2.4.2.jar')
- end
- end
-
def _report_error(output, input_filename, input_filepath)
# The output might have some clues to what exactly was wrong, and it'll
# be convenient for users if we include the subset. So we'll read the
@@ -16,7 +16,7 @@ module SC
class Builder::Strings < Builder::Base
def build(dst_path)
- data = parse_strings_js(entry.source_path)
+ data = parse_strings_js(entry[:source_path])
writelines dst_path, [data.to_yaml]
end
@@ -19,7 +19,7 @@ module SC
class Builder::Stylesheet < Builder::Base
def build(dst_path)
- lines = readlines(entry.source_path).map { |l| rewrite_inline_code(l) }
+ lines = readlines(entry[:source_path]).map { |l| rewrite_inline_code(l) }
writelines dst_path, lines
end
@@ -15,7 +15,7 @@ class Builder::Test < Builder::Html
def initialize(entry)
super(entry)
- @layout = @target.config.test_layout || 'lib/test.rhtml'
+ @layout = @target.config[:test_layout] || 'lib/test.rhtml'
end
# Always include any required test targets as well when loading unit
@@ -30,13 +30,13 @@ def expand_required_targets(target, opts = {})
def render_entry(entry)
entry.stage!
- case entry.ext
+ case entry[:ext]
when 'js'
render_jstest(entry)
when 'rhtml'
entry.target.buildfile.invoke 'render:erubis',
:entry => entry,
- :src_path => entry.staging_path,
+ :src_path => entry[:staging_path],
:context => self
end
end
@@ -47,8 +47,8 @@ def default_content_for_key; :body; end
# into its own closure so that globals defined by one test will not
# conflict with any others.
def render_jstest(entry)
- lines = readlines(entry.staging_path)
- pathname = entry.staging_path.gsub(/^.+\/staging\//,'').gsub(/"/, '\"')
+ lines = readlines(entry[:staging_path])
+ pathname = entry[:staging_path].gsub(/^.+\/staging\//,'').gsub(/"/, '\"')
lines.unshift %[<script type="text/javascript">\nif (typeof SC !== "undefined") {\n SC.mode = "TEST_MODE";\n SC.filename = "#{pathname}"; \n}\n(function() {\n]
lines.push %[\n})();\n</script>\n]
@content_for_final = (@content_for_final || '') + lines.join("")
@@ -15,8 +15,8 @@ class Builder::TestIndex < Builder::Base
def build(dst_path)
require 'json'
- items = entry.source_entries.map do |e|
- { "filename" => e.filename.ext(''), "url" => e.url }
+ items = entry[:source_entries].map do |e|
+ { "filename" => e[:filename].ext(''), "url" => e[:url] }
end
writelines dst_path, [items.to_json]
end
@@ -103,7 +103,7 @@ class Buildfile
# Determines if this directory has a buildfile or not...
def self.has_buildfile?(dir_path, buildfile_names=nil)
- buildfile_names ||= (SC.env.buildfile_names || BUILDFILE_NAMES)
+ buildfile_names ||= (SC.env[:buildfile_names] || BUILDFILE_NAMES)
buildfile_names.each do |path|
path = File.join(dir_path, path)
return true if File.exist?(path) && !File.directory?(path)
@@ -152,9 +152,9 @@ def self.define(&block)
# === Returns
# self
#
- def define!(string=nil, &block)
+ def define!(string=nil, filename="(unknown Buildfile)", &block)
context = reset_define_context :current_mode => :all
- instance_eval(string) if string
+ instance_eval(string, filename) if string
instance_eval(&block) if block_given?
load_imports
reset_define_context context
@@ -183,7 +183,7 @@ def load!(filename=nil, buildfile_names=nil)
if File.directory?(filename)
# search directory for buildfiles and load them.
- buildfile_names ||= (SC.env.buildfile_names || BUILDFILE_NAMES)
+ buildfile_names ||= (SC.env[:buildfile_names] || BUILDFILE_NAMES)
buildfile_names.each do |path|
path = File.join(filename, path)
next unless File.exist?(path) && !File.directory?(path)
@@ -195,7 +195,7 @@ def load!(filename=nil, buildfile_names=nil)
@current_path = filename
loaded_paths << filename # save loaded paths
SC.logger.debug "Loading buildfile at #{filename}"
- define!(File.read(filename)) if filename && File.exist?(filename)
+ define!(File.read(filename), filename) if filename && File.exist?(filename)
@current_path = old_path
end
return self
@@ -261,11 +261,11 @@ def intern(task_class, task_name)
#
def current_mode
- @define_context.current_mode
+ @define_context[:current_mode]
end
def current_mode=(new_mode)
- @define_context.current_mode = new_mode
+ @define_context[:current_mode] = new_mode
end
# Configures the buildfile for use with the specified target. Call this
@@ -275,7 +275,7 @@ def current_mode=(new_mode)
# self
#
def for_target(target)
- @target_name = target.target_name.to_s
+ @target_name = target[:target_name].to_s
return self
end
@@ -228,7 +228,7 @@ def execute(args=nil)
@execute_count += 1
args ||= EMPTY_TASK_ARGS
- return if SC.env.dryrun
+ return if SC.env[:dryrun]
@actions.each do |act|
case act.arity
Oops, something went wrong.

0 comments on commit 0cc2392

Please sign in to comment.