diff --git a/Gemfile b/Gemfile index 94120da85..4fb5fe2ca 100644 --- a/Gemfile +++ b/Gemfile @@ -1,80 +1,83 @@ source ENV['GEM_SOURCE'] || "https://rubygems.org" def location_for(place, fake_version = nil) if place =~ /^(git[:@][^#]*)#(.*)/ [fake_version, { :git => $1, :branch => $2, :require => false }].compact elsif place =~ /^file:\/\/(.*)/ ['>= 0', { :path => File.expand_path($1), :require => false }] else [place, { :require => false }] end end # C Ruby (MRI) or Rubinius, but NOT Windows platforms :ruby do gem 'pry', :group => :development gem 'yard', :group => :development gem 'redcarpet', '~> 2.0', :group => :development gem "racc", "1.4.9", :group => :development end gem "puppet", :path => File.dirname(__FILE__), :require => false gem "facter", *location_for(ENV['FACTER_LOCATION'] || '~> 1.6') gem "hiera", *location_for(ENV['HIERA_LOCATION'] || '~> 1.0') gem "rake", :require => false gem "rgen", "0.6.5", :require => false group(:development, :test) do # Jenkins workers may be using RSpec 2.9, so RSpec 2.11 syntax # (like `expect(value).to eq matcher`) should be avoided. gem "rspec", "~> 2.11.0", :require => false # Mocha is not compatible across minor version changes; because of this only # versions matching ~> 0.10.5 are supported. All other versions are unsupported # and can be expected to fail. gem "mocha", "~> 0.10.5", :require => false gem "yarjuf", "~> 1.0" # json-schema does not support windows, so use the 'ruby' platform to exclude it on windows platforms :ruby do # json-schema uses multi_json, but chokes with multi_json 1.7.9, so prefer 1.7.7 gem "multi_json", "1.7.7", :require => false gem "json-schema", "2.1.1", :require => false end + platforms :ruby_19, :ruby_20 do + gem 'ruby-prof' + end end group(:extra) do gem "rack", "~> 1.4", :require => false gem "activerecord", '~> 3.2', :require => false gem "couchrest", '~> 1.0', :require => false gem "net-ssh", '~> 2.1', :require => false gem "puppetlabs_spec_helper", :require => false gem "sqlite3", :require => false gem "stomp", :require => false gem "tzinfo", :require => false gem "msgpack", :require => false end require 'yaml' data = YAML.load_file(File.join(File.dirname(__FILE__), 'ext', 'project_data.yaml')) bundle_platforms = data['bundle_platforms'] data['gem_platform_dependencies'].each_pair do |gem_platform, info| if bundle_deps = info['gem_runtime_dependencies'] bundle_platform = bundle_platforms[gem_platform] or raise "Missing bundle_platform" platform(bundle_platform.intern) do bundle_deps.each_pair do |name, version| gem(name, version, :require => false) end end end end if File.exists? "#{__FILE__}.local" eval(File.read("#{__FILE__}.local"), binding) end # vim:filetype=ruby diff --git a/tasks/benchmark.rake b/tasks/benchmark.rake index cbb8bcd0f..d95cd552d 100644 --- a/tasks/benchmark.rake +++ b/tasks/benchmark.rake @@ -1,87 +1,108 @@ require 'benchmark' require 'tmpdir' require 'erb' require 'ostruct' require 'open3' desc "Execute all puppet benchmarks." task :benchmark => ["benchmark:many_modules"] namespace :benchmark do desc "Benchmark scenario: many manifests spread across many modules. Benchmark target: catalog compilation." task :many_modules => "many_modules:run" namespace :many_modules do task :setup do ENV['SIZE'] ||= '100' ENV['TARGET'] ||= Dir.mktmpdir("many_modules") ENV['TARGET'] = File.expand_path(ENV['TARGET']) mkdir_p(ENV['TARGET']) end desc "Generate the scenario" task :generate => :setup do size = ENV['SIZE'].to_i environment = File.join(ENV['TARGET'], 'environments', 'benchmarking') templates = File.join('benchmarks', 'many_modules') mkdir_p(File.join(environment, 'modules')) mkdir_p(File.join(environment, 'manifests')) render(File.join(templates, 'site.pp.erb'), File.join(environment, 'manifests', 'site.pp'), :size => size) size.times do |i| module_name = "module#{i}" manifests = File.join(environment, 'modules', module_name, 'manifests') mkdir_p(manifests) render(File.join(templates, 'module', 'init.pp.erb'), File.join(manifests, 'init.pp'), :name => module_name) render(File.join(templates, 'module', 'internal.pp.erb'), File.join(manifests, 'internal.pp'), :name => module_name) end render(File.join(templates, 'puppet.conf.erb'), File.join(ENV['TARGET'], 'puppet.conf'), :location => ENV['TARGET']) end task :run => :generate do require 'puppet' include Benchmark config = File.join(ENV['TARGET'], 'puppet.conf') Puppet.initialize_settings(['--config', config]) Benchmark.benchmark(CAPTION, 10, FORMAT, "> total:", "> avg:") do |b| times = [] 10.times do |i| times << b.report("Run #{i + 1}") do - env = Puppet.lookup(:environments).get('benchmarking') - node = Puppet::Node.new("testing", :environment => env) - Puppet::Resource::Catalog.indirection.find("testing", :use_node => node) + run end end sum = times.inject(Benchmark::Tms.new, &:+) [sum, sum / times.length] end end + + task :profile => :generate do + require 'puppet' + require 'ruby-prof' + + RubyProf.start + config = File.join(ENV['TARGET'], 'puppet.conf') + Puppet.initialize_settings(['--config', config]) + run + result = RubyProf.stop + + printer = RubyProf::CallTreePrinter.new(result) + File.open(File.join("callgrind.many_modules.#{Time.now.to_i}.trace"), "w") do |f| + printer.print(f) + end + + end + + def run + env = Puppet.lookup(:environments).get('benchmarking') + node = Puppet::Node.new("testing", :environment => env) + Puppet::Resource::Catalog.indirection.find("testing", :use_node => node) + end end def render(erb_file, output_file, bindings) site = ERB.new(File.read(erb_file)) File.open(output_file, 'w') do |fh| fh.write(site.result(OpenStruct.new(bindings).instance_eval { binding })) end end end