diff --git a/middleman-core/bin/middleman b/middleman-core/bin/middleman index e7ccc0d5..7f66c2c7 100755 --- a/middleman-core/bin/middleman +++ b/middleman-core/bin/middleman @@ -7,6 +7,12 @@ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir) moredir = File.expand_path(File.join(File.dirname(File.dirname(libdir)), "middleman-more", "lib", "middleman-more")) $LOAD_PATH.unshift(moredir) unless $LOAD_PATH.include?(moredir) +require 'middleman-core/profiling' +if ARGV.include? '--profile' + Middleman::Profiling.profiler = Middleman::Profiling::RubyProfProfiler.new +end +Middleman::Profiling.start + require "middleman-core/load_paths" Middleman.setup_load_paths @@ -16,4 +22,4 @@ require "middleman-core/cli" Dir.chdir(ENV["MM_ROOT"]) if ENV["MM_ROOT"] # Start the CLI -Middleman::Cli::Base.start \ No newline at end of file +Middleman::Cli::Base.start diff --git a/middleman-core/lib/middleman-core/cli.rb b/middleman-core/lib/middleman-core/cli.rb index 284df439..9dccfae2 100644 --- a/middleman-core/lib/middleman-core/cli.rb +++ b/middleman-core/lib/middleman-core/cli.rb @@ -9,7 +9,6 @@ module Middleman # The base task from which everything else etends class Base < Thor - class << self def start(*args) # Change flag to a module @@ -23,7 +22,7 @@ module Middleman super end end - + desc "version", "Show version" def version require 'middleman-core/version' @@ -87,4 +86,4 @@ require "middleman-core/cli/init" require "middleman-core/cli/bundler" require "middleman-core/cli/extension" require "middleman-core/cli/server" -require "middleman-core/cli/build" \ No newline at end of file +require "middleman-core/cli/build" diff --git a/middleman-core/lib/middleman-core/cli/build.rb b/middleman-core/lib/middleman-core/cli/build.rb index 12451ea1..2d71c666 100644 --- a/middleman-core/lib/middleman-core/cli/build.rb +++ b/middleman-core/lib/middleman-core/cli/build.rb @@ -32,6 +32,10 @@ module Middleman::Cli :type => :string, :default => false, :desc => 'Print instrument messages' + method_option :profile, + :type => :boolean, + :default => false, + :desc => 'Generate profiling report for the build' # Core build Thor command # @return [void] @@ -257,6 +261,8 @@ module Middleman::Cli @cleaning_queue.delete(Pathname.new(output_path).realpath) if cleaning? end + + ::Middleman::Profiling.report("build") end end diff --git a/middleman-core/lib/middleman-core/cli/server.rb b/middleman-core/lib/middleman-core/cli/server.rb index f34e487f..73adcbd9 100644 --- a/middleman-core/lib/middleman-core/cli/server.rb +++ b/middleman-core/lib/middleman-core/cli/server.rb @@ -33,7 +33,11 @@ module Middleman::Cli :type => :boolean, :default => false, :desc => 'Disable the file change and delete watcher process' - + method_option :profile, + :type => :boolean, + :default => false, + :desc => 'Generate profiling report for server startup' + # Start the server def server require "middleman-core" diff --git a/middleman-core/lib/middleman-core/core_extensions/request.rb b/middleman-core/lib/middleman-core/core_extensions/request.rb index c3491327..065b6b59 100644 --- a/middleman-core/lib/middleman-core/core_extensions/request.rb +++ b/middleman-core/lib/middleman-core/core_extensions/request.rb @@ -204,6 +204,7 @@ module Middleman process_request(env, req, res) res.status = 404 + res.finish end end diff --git a/middleman-core/lib/middleman-core/preview_server.rb b/middleman-core/lib/middleman-core/preview_server.rb index 255fe20d..7d90bd82 100644 --- a/middleman-core/lib/middleman-core/preview_server.rb +++ b/middleman-core/lib/middleman-core/preview_server.rb @@ -46,7 +46,8 @@ module Middleman # Save the last-used options so it may be re-used when # reloading later on. @last_options = options - + ::Middleman::Profiling.report("server_start") + @webrick.start end end diff --git a/middleman-core/lib/middleman-core/profiling.rb b/middleman-core/lib/middleman-core/profiling.rb new file mode 100644 index 00000000..648101ce --- /dev/null +++ b/middleman-core/lib/middleman-core/profiling.rb @@ -0,0 +1,58 @@ +module Middleman + module Profiling + + # The profiler instance. There can only be one! + def self.profiler=(prof) + @profiler = prof + end + def self.profiler + @profiler ||= NullProfiler.new + end + + # Start the profiler + def self.start + profiler.start + end + + # Stop the profiler and generate a report. Make sure to call start first + def self.report(report_name) + profiler.report(report_name) + end + + # A profiler that does nothing. The default. + class NullProfiler + def start + end + + def report + end + end + + # A profiler that uses ruby-prof + class RubyProfProfiler + def initialize + begin + require 'ruby-prof' + rescue LoadError + raise "To use the --profile option, you must 'gem install ruby-prof' (and include it in your Gemfile if running under bundle exec)" + end + end + + def start + RubyProf.start + end + + def report(report_name) + result = RubyProf.stop + + printer = RubyProf::GraphHtmlPrinter.new(result) + outfile = File.join("profile", report_name) + outfile = (outfile + '.html') unless outfile.end_with? '.html' + FileUtils.mkdir_p(File.dirname(outfile)) + File.open(outfile, 'w') do |f| + printer.print(f, :min_percent=> 1) + end + end + end + end +end