Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RailsConf 2015 Keynote

RailsConf 2015 Keynote

Aaron Patterson

May 13, 2015
Tweet

More Decks by Aaron Patterson

Other Decks in Technology

Transcript

  1. Benchmark Benchmark.ips do |bm| bm.report 'INDEX: Integration Test' do Minitest.run_one_method(IntegrationTest,

    'test_index') end bm.report 'INDEX: Functional Test' do Minitest.run_one_method(ControllerTest, 'test_index') end bm.compare! end Controller Integration Compare
  2. Result Calculating ------------------------------------- INDEX: Integration Test 15.000 i/100ms INDEX: Functional

    Test 39.000 i/100ms ------------------------------------------------- INDEX: Integration Test 158.019 (± 8.2%) i/s - 795.000 INDEX: Functional Test 390.853 (± 9.0%) i/s - 1.950k Comparison: INDEX: Functional Test: 390.9 i/s INDEX: Integration Test: 158.0 i/s - 2.47x slower Comparison
  3. Stack ================================== Mode: cpu(1000) Samples: 3280 (0.00% miss rate) GC:

    134 (4.09%) ================================== TOTAL (pct) SAMPLES (pct) FRAME 3146 (95.9%) 1740 (53.0%) Minitest::Runnable.on_signal 483 (14.7%) 483 (14.7%) Dependencies#search_for_file 207 (6.3%) 191 (5.8%) SQLite3::Database#prepare 95 (2.9%) 95 (2.9%) Inflector#underscore 47 (1.4%) 46 (1.4%) TestRequest#initialize
  4. on_signal def self.on_signal name, action # :nodoc: supported = SIGNALS[name]

    old_trap = trap name do old_trap.call if old_trap.respond_to? :call action.call end if supported yield ensure trap name, old_trap if supported end
  5. Results ================================== Mode: cpu(1000) Samples: 4246 (0.00% miss rate) GC:

    386 (9.09%) ================================== TOTAL (pct) SAMPLES (pct) FRAME 220 (5.2%) 185 (4.4%) SQLite3::Database#prepare 148 (3.5%) 131 (3.1%) TestRequest#initialize 113 (2.7%) 113 (2.7%) Event#initialize 105 (2.5%) 105 (2.5%) PerThreadRegistry#instance
  6. Time the process $ time ruby benchmark.rb real 0m12.358s user

    0m11.732s sys 0m0.498s $ time ruby benchmark.rb real 0m12.055s user 0m11.462s sys 0m0.475s Before After
  7. &

  8. Stack (CPU) ================================== Mode: cpu(1000) Samples: 3280 (0.00% miss rate)

    GC: 134 (4.09%) ================================== TOTAL (pct) SAMPLES (pct) FRAME 3146 (95.9%) 1740 (53.0%) Minitest::Runnable.on_signal 483 (14.7%) 483 (14.7%) Dependencies#search_for_file 207 (6.3%) 191 (5.8%) SQLite3::Database#prepare 95 (2.9%) 95 (2.9%) Inflector#underscore 47 (1.4%) 46 (1.4%) TestRequest#initialize
  9. Stack (WALL) ================================== Mode: wall(1000) Samples: 8797 (0.11% miss rate)

    GC: 535 (6.08%) ================================== TOTAL (pct) SAMPLES (pct) FRAME 286 (3.3%) 286 (3.3%) PerThreadRegistry#instance 233 (2.6%) 233 (2.6%) Formatter#non_recursive 336 (3.8%) 227 (2.6%) Class#class_attribute 209 (2.4%) 209 (2.4%) NonConcurrentCacheBackend#[] 198 (2.3%) 198 (2.3%) ActiveRecord::Base.logger
  10. '

  11. Stack (WALL) ================================== Mode: wall(1000) Samples: 20168 (2.95% miss rate)

    GC: 1247 (6.18%) ================================== TOTAL (pct) SAMPLES (pct) FRAME 6401 (31.7%) 5622 (27.9%) block in Module#delegate 495 (2.5%) 495 (2.5%) PerThreadRegistry#instance 341 (1.7%) 341 (1.7%) NonConcurrentCacheBackend#[] 317 (1.6%) 317 (1.6%) Set#include?
  12. Patch - delegate :url_for, :optimize_routes_generation?, to: '@_routes' + def url_for(options)

    + @_routes.url_for(options) + end + + def optimize_routes_generation? + @_routes.optimize_routes_generation? + end +
  13. Result Calculating ------------------------------------- INDEX: Integration Test 23.000 i/100ms INDEX: Functional

    Test 37.000 i/100ms ------------------------------------------------- INDEX: Integration Test 251.487 (±12.7%) i/s - 1.242k INDEX: Functional Test 365.112 (±11.0%) i/s - 1.813k Comparison: INDEX: Functional Test: 365.1 i/s INDEX: Integration Test: 251.5 i/s - 1.45x slower Comparison
  14. Verify $ time ruby test.rb real 0m26.821s user 0m25.277s sys

    0m0.903s $ time ruby test.rb real 0m16.632s user 0m15.709s sys 0m0.638s Before After
  15. bin stub source code #!/Users/aaron/.rbenv/versions/ruby-trunk/bin/ruby # # This file was

    generated by RubyGems. # # The application 'bundler' is installed as part of a gem, and # this file is here to facilitate running it. # # some unimportant stuff happens here! gem 'bundler', version load Gem.bin_path('bundler', 'bundle', version)
  16. gem

  17. Load Path Manipulation > x = $LOAD_PATH.dup; nil => nil

    > gem 'bundler' => true > $LOAD_PATH - x => ["/Users/aaron/.rbenv/versions/ruby-trunk/lib/ruby/gems/2.3.0/gems/ bundler-1.9.2/lib"]
  18. time to require one file Time in seconds 0 0.08

    0.16 0.24 0.32 Number of Gems on the system 0 100 200 300 400 500 600 700 800 900 1000 best worst
  19. allocations to require one file Number of allocations 0 22500

    45000 67500 90000 Number of Gems on the system 0 100 200 300 400 500 600 700 800 900 1000 best worst
  20. time to activate one gem Time in seconds 0 0.06

    0.12 0.18 0.24 Number of Gems on the system 0 100 200 300 400 500 600 700 800 900 1000 best worst
  21. allocations to activate one gem Number of allocations 0 10000

    20000 30000 40000 Number of Gems on the system 0 100 200 300 400 500 600 700 800 900 1000
  22. `bundle update` with one gem Time in Seconds 0 0.2

    0.4 0.6 0.8 Number of Gems on the system 100 200 300 400 500 600 700 800 900 1000
  23. `bundle exec` with one gem Time in Seconds 0 0.2

    0.4 0.6 0.8 Number of Gems on the system 100 200 300 400 500 600 700 800 900 1000
  24. `bundle exec` time Time in seconds 1.44 1.45 1.46 1.47

    1.48 Number of gems in the gemfile 0 100 200 300 400 500 600 700 800 900 1000 y = 0.0008x + 1.4603 R² = 0.1323
  25. `bundle update` time Time in Seconds 0 17.5 35 52.5

    70 Number of Gems in the Gemfile 0 100 200 300 400 500 600 700 800 900 1000 y = 0.6984x2 - 2.9466x + 13.856 R² = 0.999
  26. R Code - Fit curve > bundler <- read.csv(file="~/bundle_test/ run_bundle_updats.csv",head=TRUE,sep=",")

    > fit2 <- lm(bundler$time ~ poly(bundler$gems, 2, raw = TRUE)) > xx <- seq(0, 1000, length=11) > plot(bundler$gems, bundler$time) > lines(xx, predict(fit2, data.frame(x = xx)), col="red")
  27. R Code - Coefficients > coefficients(fit2) (Intercept) poly(bundler$gems, 2, raw

    = TRUE)1 poly(bundler$gems, 2, raw = TRUE)2 1.160827e+01 -1.549806e-02 6.984136e-05 > summary(fit2)$r.squared [1] 0.9989536 >
  28. Make Predictions > second_order <- function(newdist, model) { + coefs

    <- coef(model) + res <- coefs[1] + (coefs[2] * newdist) + (coefs[3] * newdist^2) + return(res) + } > second_order(0, fit2) (Intercept) 11.60827 > second_order(10000, fit2) (Intercept) 6840.763 empty gemfile 10k gemfile
  29. bin stub source code #!/Users/aaron/.rbenv/versions/ruby-trunk/bin/ruby # # This file was

    generated by RubyGems. # # The application 'bundler' is installed as part of a gem, and # this file is here to facilitate running it. # # some unimportant stuff happens here! gem 'bundler', version load Gem.bin_path('bundler', 'bundle', version) gem name
  30. Spec loading code today def get_spec name spec_cache = Dir[File.join(dir,

    "*.gemspec")] spec_cache.find { |spec| spec.name == name } end
  31. bundle -v against 100k gems [aaron@TC rubygems (master)]$ time GEM_HOME=`pwd`/100k_gems

    GEM_PATH=`pwd`/100k_gems ruby -I lib 100k_gems/bin/bundle -v Bundler version 1.9.4 real 0m50.045s user 0m15.815s sys 0m11.967s
  32. Spec loading code I want def get_spec name spec_cache =

    Dir[File.join(dir, "#{name}-*.gemspec")] spec_cache.find { |spec| spec.name == name } end
  33. bundle -v against 100k gems [aaron@TC rubygems (specs)]$ time GEM_HOME=`pwd`/100k_gems

    GEM_PATH=`pwd`/100k_gems ruby -I lib 100k_gems/bin/bundle -v Bundler version 1.9.4 real 0m0.632s user 0m0.479s sys 0m0.124s