additional perf work

feature/manifest
Thomas Reynolds 2016-01-22 14:25:02 -08:00
parent e0818e2118
commit b8c0fd34e7
9 changed files with 99 additions and 53 deletions

View File

@ -52,7 +52,7 @@ module Middleman::Cli
::Middleman::Logger.singleton(verbose, instrument)
::Middleman::Util.instrument 'builder_setup' do
::Middleman::Util.instrument 'builder.setup' do
@app = ::Middleman::Application.new do
config[:mode] = :build
config[:environment] = env
@ -67,7 +67,7 @@ module Middleman::Cli
builder.on_build_event(&method(:on_event))
end
::Middleman::Util.instrument 'builder_run' do
::Middleman::Util.instrument 'builder.run' do
if builder.run!
clean_directories! if options['clean']
shell.say 'Project built successfully.'

View File

@ -51,18 +51,31 @@ module Middleman
@has_error = false
@events = {}
@app.execute_callbacks(:before_build, [self])
::Middleman::Util.instrument 'builder.before' do
@app.execute_callbacks(:before_build, [self])
end
queue_current_paths if @cleaning
::Middleman::Util.instrument 'builder.queue' do
queue_current_paths if @cleaning
end
prerender_css
output_files
::Middleman::Util.instrument 'builder.prerender' do
prerender_css
end
clean! if @cleaning
::Middleman::Util.instrument 'builder.output' do
output_files
end
::Middleman::Util.instrument 'builder.clean' do
clean! if @cleaning
end
::Middleman::Profiling.report('build')
@app.execute_callbacks(:after_build, [self])
::Middleman::Util.instrument 'builder.after' do
@app.execute_callbacks(:after_build, [self])
end
!@has_error
end
@ -73,14 +86,18 @@ module Middleman
def prerender_css
logger.debug '== Prerendering CSS'
css_files = @app.sitemap.resources
.select { |resource| resource.ext == '.css' }
.each(&method(:output_resource))
css_files = ::Middleman::Util.instrument 'builder.prerender.output' do
@app.sitemap.resources
.select { |resource| resource.ext == '.css' }
.each(&method(:output_resource))
end
# Double-check for compass sprites
if @app.files.find_new_files!.length > 0
logger.debug '== Checking for Compass sprites'
@app.sitemap.ensure_resource_list_updated!
::Middleman::Util.instrument 'builder.prerender.check-files' do
# Double-check for compass sprites
if @app.files.find_new_files!.length > 0
logger.debug '== Checking for Compass sprites'
@app.sitemap.ensure_resource_list_updated!
end
end
css_files
@ -92,11 +109,15 @@ module Middleman
def output_files
logger.debug '== Building files'
@app.sitemap.resources
.sort_by { |resource| SORT_ORDER.index(resource.ext) || 100 }
resources = @app.sitemap.resources
.reject { |resource| resource.ext == '.css' }
.select { |resource| !@glob || File.fnmatch(@glob, resource.destination_path) }
.each(&method(:output_resource))
.sort_by { |resource| SORT_ORDER.index(resource.ext) || 100 }
if @glob
resources = resources.select { |resource| File.fnmatch(@glob, resource.destination_path) }
end
resources.each(&method(:output_resource))
end
# Figure out the correct event mode.
@ -162,25 +183,29 @@ module Middleman
# @return [void]
Contract IsA['Middleman::Sitemap::Resource'] => Any
def output_resource(resource)
output_file = @build_dir + resource.destination_path.gsub('%20', ' ')
output_file = nil
begin
if resource.binary?
export_file!(output_file, resource.file_descriptor[:full_path])
else
response = @rack.get(::URI.escape(resource.request_path))
::Middleman::Util.instrument "builder.output.resource", path: File.basename(resource.destination_path) do
output_file = @build_dir + resource.destination_path.gsub('%20', ' ')
# If we get a response, save it to a tempfile.
if response.status == 200
export_file!(output_file, binary_encode(response.body))
begin
if resource.binary?
export_file!(output_file, resource.file_descriptor[:full_path])
else
@has_error = true
trigger(:error, output_file, response.body)
response = @rack.get(::URI.escape(resource.request_path))
# If we get a response, save it to a tempfile.
if response.status == 200
export_file!(output_file, binary_encode(response.body))
else
@has_error = true
trigger(:error, output_file, response.body)
end
end
rescue => e
@has_error = true
trigger(:error, output_file, "#{e}\n#{e.backtrace.join("\n")}")
end
rescue => e
@has_error = true
trigger(:error, output_file, "#{e}\n#{e.backtrace.join("\n")}")
end
return unless @cleaning

View File

@ -57,6 +57,7 @@ module Middleman
@app = app
@data_file_matcher = data_file_matcher
@local_data = {}
@local_data_enhanced = nil
@local_sources = {}
@callback_sources = {}
end
@ -117,6 +118,8 @@ module Middleman
end
data_branch[basename] = data
@local_data_enhanced = nil
end
# Remove a given file from the internal cache
@ -137,6 +140,8 @@ module Middleman
end
data_branch.delete(basename) if data_branch.key?(basename)
@local_data_enhanced = nil
end
# Get a hash from either internal static data or a callback
@ -151,8 +156,7 @@ module Middleman
callbacks[path.to_s].call
end
response = ::Middleman::Util.recursively_enhance(response)
response
::Middleman::Util.recursively_enhance(response)
end
# "Magically" find namespaces of data if they exist
@ -162,7 +166,8 @@ module Middleman
def method_missing(path)
if @local_data.key?(path.to_s)
# Any way to cache this?
return ::Middleman::Util.recursively_enhance(@local_data[path.to_s])
@local_data_enhanced ||= ::Middleman::Util.recursively_enhance(@local_data)
return @local_data_enhanced[path.to_s]
else
result = data_for_path(path)
return result if result

View File

@ -73,9 +73,10 @@ module Middleman
# end
# Render using Tilt
content = ::Middleman::Util.instrument 'render.tilt', path: path do
template.render(context, locs, &block)
end
# content = ::Middleman::Util.instrument 'render.tilt', path: path do
# template.render(context, locs, &block)
# end
content = template.render(context, locs, &block)
# Allow hooks to manipulate the result after render
content = @app.callbacks_for(:after_render).reduce(content) do |sum, callback|

View File

@ -40,6 +40,7 @@ module Middleman
return if @instrumenting.is_a?(String) && @instrumenting != 'instrument' && !message.include?(@instrumenting)
evt = ::ActiveSupport::Notifications::Event.new(message, *args)
return unless evt.duration > 30
info "== Instrument (#{evt.name.sub(/.middleman$/, '')}): #{evt.duration}ms\n#{args.last}"
end
end

View File

@ -66,6 +66,8 @@ module Middleman
# Page are data that is exposed through this resource's data member.
# Note: It is named 'page' for backwards compatibility with older MM.
@metadata = { options: {}, locals: {}, page: {} }
@page_data = nil
end
# Whether this resource has a template file
@ -91,6 +93,7 @@ module Middleman
# Note: It is named 'page' for backwards compatibility with older MM.
Contract METADATA_HASH => METADATA_HASH
def add_metadata(meta={})
@page_data = nil
@metadata.deep_merge!(meta)
end
@ -98,7 +101,7 @@ module Middleman
# @return [Hash]
Contract RespondTo[:indifferent_access?]
def data
::Middleman::Util.recursively_enhance(metadata[:page])
@page_data ||= ::Middleman::Util.recursively_enhance(metadata[:page])
end
# Options about how this resource is rendered, such as its :layout,
@ -129,7 +132,6 @@ module Middleman
def render(opts={}, locs={})
return ::Middleman::FileRenderer.new(@app, file_descriptor[:full_path].to_s).template_data_for_file unless template?
# ::Middleman::Util.instrument 'render.resource', path: file_descriptor[:full_path].to_s, destination_path: destination_path do
md = metadata
opts = md[:options].deep_merge(opts)
locs = md[:locals].deep_merge(locs)
@ -140,7 +142,6 @@ module Middleman
renderer = ::Middleman::TemplateRenderer.new(@app, file_descriptor[:full_path].to_s)
renderer.render(locs, opts)
# end
end
# A path without the directory index - so foo/index.html becomes

View File

@ -185,9 +185,7 @@ module Middleman
new_files = ::Middleman::Util.all_files_under(@directory.to_s)
.reject { |p| @files.key?(p) }
update(new_files, [])
new_files
update(new_files, []).flatten.map { |s| s[:full_path] }
end
# Manually trigger update events.
@ -198,14 +196,14 @@ module Middleman
updated = ::Middleman::Util.all_files_under(@directory.to_s)
removed = @files.keys.reject { |p| updated.include?(p) }
update(updated, removed)
result = update(updated, removed)
if @waiting_for_existence && @directory.exist?
@waiting_for_existence = false
listen!
end
updated + removed
result.flatten.map { |s| s[:full_path] }
end
# Work around this bug: http://bugs.ruby-lang.org/issues/4521
@ -238,7 +236,7 @@ module Middleman
#
# @param [String, Pathname] path The updated file path.
# @return [void]
Contract ArrayOf[Pathname], ArrayOf[Pathname] => Any
Contract ArrayOf[Pathname], ArrayOf[Pathname] => ArrayOf[ArrayOf[IsA['Middleman::SourceFile']]]
def update(updated_paths, removed_paths)
valid_updates = updated_paths
.map { |p| @files[p] || path_to_source_file(p, @directory, @type, @options[:destination_dir]) }
@ -271,6 +269,8 @@ module Middleman
valid_removes,
self
]) unless valid_updates.empty? && valid_removes.empty?
[valid_updates, valid_removes]
end
# Convert a path to a file resprentation.

View File

@ -133,12 +133,21 @@ module Middleman
# Add extension helpers to context.
@app.extensions.add_exposed_to_context(context)
content = _render_with_all_renderers(path, locs, context, opts, &block)
content = ::Middleman::Util.instrument 'builder.output.resource.render-template', path: File.basename(path) do
_render_with_all_renderers(path, locs, context, opts, &block)
end
# If we need a layout and have a layout, use it
if layout_file = fetch_layout(engine, options)
layout_renderer = ::Middleman::FileRenderer.new(@app, layout_file[:relative_path].to_s)
content = layout_renderer.render(locals, options, context) { content }
layout_file = fetch_layout(engine, options)
if layout_file
content = ::Middleman::Util.instrument 'builder.output.resource.render-layout', path: File.basename(layout_file[:relative_path].to_s) do
if layout_file = fetch_layout(engine, options)
layout_renderer = ::Middleman::FileRenderer.new(@app, layout_file[:relative_path].to_s)
layout_renderer.render(locals, options, context) { content }
else
content
end
end
end
# Return result

View File

@ -98,7 +98,7 @@ module Middleman
# @private
# @param [Hash] data Normal hash
# @return [Hash]
Contract Maybe[Hash] => Maybe[Or[Array, EnhancedHash]]
Contract Any => Maybe[Or[Array, EnhancedHash]]
def recursively_enhance(obj)
if obj.is_a? ::Array
obj.map { |e| recursively_enhance(e) }
@ -480,6 +480,8 @@ module Middleman
# @return [String]
Contract String => ArrayOf[String]
def collect_extensions(path)
return [] if File.basename(path).start_with?('.')
result = []
step_through_extensions(path) { |e| result << e }
@ -495,6 +497,8 @@ module Middleman
# @return [Middleman::SourceFile] All related file paths, not including the source file paths.
Contract ::Middleman::Application, ArrayOf[Pathname] => ArrayOf[::Middleman::SourceFile]
def find_related_files(app, files)
return [] if files.empty?
all_extensions = files.flat_map { |f| collect_extensions(f.to_s) }
sass_type_aliasing = ['.scss', '.sass']