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

RailsConf 2015 Keynote

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

RailsConf 2015 Keynote

Avatar for Aaron Patterson

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