1. 07 12月, 2017 1 次提交
  2. 08 11月, 2017 1 次提交
    • D
      Performance improvements for add_method_to_attributes! · c57e914c
      Dillon Welch 提交于
      Prevents two string allocations per method call for common REST verbs
      plus a ~1.5x speedup for :get in particular
      
      ```ruby
      begin
        require "bundler/inline"
      rescue LoadError => e
        $stderr.puts "Bundler version 1.10 or later is required. Please update
                      your Bundler"
        raise e
      end
      
      gemfile(true) do
        source "https://rubygems.org"
      
        gem "benchmark-ips"
        gem "rails"
      end
      
      def allocate_count
        GC.disable
        before = ObjectSpace.count_objects
        yield
        after = ObjectSpace.count_objects
        after.each { |k,v| after[k] = v - before[k] }
        after[:T_HASH] -= 1 # probe effect - we created the before hash.
        GC.enable
        result = after.reject { |k,v| v == 0 }
        GC.start
        result
      end
      
      @html_options = {}
      
      def master_version
        if @method && @method.to_s.downcase != "get" && @html_options["rel".freeze] !~ /nofollow/
          @html_options["rel".freeze] = "#{@html_options["rel".freeze]} nofollow".lstrip
        end
        @html_options["data-method".freeze] = @method
      end
      
      def fast_version
        if method_not_get_method?(@method) && @html_options["rel".freeze] !~ /nofollow/
          @html_options["rel".freeze] = "#{@html_options["rel".freeze]} nofollow".lstrip
        end
        @html_options["data-method".freeze] = @method
      end
      
      STRINGIFIED_COMMON_METHODS = {
        get:    'get',
        delete: 'delete',
        patch:  'patch',
        post:   'post',
        put:    'put',
      }.freeze
      
      def method_not_get_method?(method)
        return false unless method
        (STRINGIFIED_COMMON_METHODS[method] || method.to_s.downcase) != 'get'
      end
      
      puts 'get'
      @method = :get
      
      puts "master_version"
      puts allocate_count { 1000.times { master_version } }
      puts "fast_version"
      puts allocate_count { 1000.times { fast_version } }
      
      Benchmark.ips do |x|
        x.report("master_version") { master_version }
        x.report("fast_version")     { fast_version }
        x.compare!
      end
      
      puts 'delete'
      @method = :delete
      
      puts "master_version"
      puts allocate_count { 1000.times { master_version } }
      puts "fast_version"
      puts allocate_count { 1000.times { fast_version } }
      
      Benchmark.ips do |x|
        x.report("master_version") { master_version }
        x.report("fast_version")     { fast_version }
        x.compare!
      end
      ```
      
      ```
      get
      master_version
      {:FREE=>-1819, :T_STRING=>2052}
      fast_version
      {:FREE=>-1}
      Warming up --------------------------------------
            master_version   140.839k i/100ms
              fast_version   175.639k i/100ms
      Calculating -------------------------------------
            master_version      2.683M (± 7.1%) i/s -     13.380M in   5.013447s
              fast_version      3.988M (±10.1%) i/s -     19.847M in   5.039580s
      
      Comparison:
              fast_version:  3988340.3 i/s
            master_version:  2683336.2 i/s - 1.49x  slower
      
      delete
      master_version
      {:FREE=>-5003, :T_STRING=>3003, :T_MATCH=>999, :T_IMEMO=>1000}
      fast_version
      {:FREE=>-3002, :T_STRING=>1001, :T_MATCH=>1000, :T_IMEMO=>1000}
      Warming up --------------------------------------
            master_version    47.221k i/100ms
              fast_version    44.153k i/100ms
      Calculating -------------------------------------
            master_version    597.881k (±11.4%) i/s -      2.975M in   5.047200s
              fast_version    686.014k (±11.6%) i/s -      3.400M in   5.036564s
      
      Comparison:
              fast_version:   686014.5 i/s
            master_version:   597881.4 i/s - same-ish: difference falls within error
      ```
      c57e914c
  3. 03 11月, 2017 2 次提交
    • D
      Fix typo · ec13ef75
      Dillon Welch 提交于
      ec13ef75
    • D
      Use blank? check instead of key? check · d404e2cb
      Dillon Welch 提交于
      This allows us to prevent an extra string allocation when there is a rel
      argument and performs better/within error of the key check for other
      scenarios such as passing in rel: nil
      
      ```ruby
      begin
        require "bundler/inline"
      rescue LoadError => e
        $stderr.puts "Bundler version 1.10 or later is required. Please update
                      your Bundler"
        raise e
      end
      
      gemfile(true) do
        source "https://rubygems.org"
      
        gem "benchmark-ips"
        gem "rails"
      end
      
      def allocate_count
        GC.disable
        before = ObjectSpace.count_objects
        yield
        after = ObjectSpace.count_objects
        after.each { |k,v| after[k] = v - before[k] }
        after[:T_HASH] -= 1 # probe effect - we created the before hash.
        GC.enable
        result = after.reject { |k,v| v == 0 }
        GC.start
        result
      end
      
      @hash = {}
      
      def master_version
        "#{@hash["rel"]} nofollow".lstrip
      end
      
      def key_version
        if @hash.key?("rel")
          "#{@hash["rel"]} nofollow".lstrip
        else
          "nofollow"
        end
      end
      
      def present_version
        if @hash["rel"].present?
          "#{@hash["rel"]} nofollow"
        else
          "nofollow".freeze
        end
      end
      
      def nil_version
        if @hash["rel"].nil?
          "nofollow".freeze
        else
          "#{@hash["rel"]} nofollow"
        end
      end
      
      def blank_version
        if @hash["rel"].blank?
          "nofollow".freeze
        else
          "#{@hash["rel"]} nofollow"
        end
      end
      
      def test
        puts "master_version"
        puts allocate_count { 1000.times { master_version } }
        puts "key_version"
        puts allocate_count { 1000.times { key_version } }
        puts "present_version"
        puts allocate_count { 1000.times { present_version } }
        puts "nil_version"
        puts allocate_count { 1000.times { nil_version } }
        puts "blank_version"
        puts allocate_count { 1000.times { blank_version } }
      
        Benchmark.ips do |x|
          x.report("master_version")  { master_version }
          x.report("key_version")     { key_version }
          x.report("present_version") { present_version }
          x.report("nil_version")     { nil_version }
          x.report("blank_version")     { blank_version }
          x.compare!
        end
      end
      
      puts 'no rel key'
      
      test
      
      puts 'rel key with real stuff'
      
      @hash['rel'] = 'hi'.freeze
      
      test
      
      puts 'rel key with nil'
      
      @hash['rel'] = nil
      
      test
      
      puts 'rel key with ""'
      
      @hash['rel'] = ""
      
      test
      ```
      
      ```
      no rel key
      master_version
      {:FREE=>-2818, :T_STRING=>3052}
      key_version
      {:FREE=>-1}
      present_version
      {:FREE=>-1}
      nil_version
      {:FREE=>-1}
      blank_version
      {:FREE=>-1}
      Warming up --------------------------------------
            master_version   124.677k i/100ms
               key_version   227.992k i/100ms
           present_version   208.068k i/100ms
               nil_version   235.272k i/100ms
             blank_version   176.274k i/100ms
      Calculating -------------------------------------
            master_version      1.968M (±10.8%) i/s -      9.725M in   5.010763s
               key_version      7.734M (±11.2%) i/s -     38.075M in   5.001613s
           present_version      5.688M (±11.4%) i/s -     28.089M in   5.019560s
               nil_version      6.965M (±10.2%) i/s -     34.585M in   5.024806s
             blank_version      6.139M (±18.7%) i/s -     29.085M in   5.010919s
      
      Comparison:
               key_version:  7734058.3 i/s
               nil_version:  6965050.2 i/s - same-ish: difference falls within error
             blank_version:  6138744.3 i/s - same-ish: difference falls within error
           present_version:  5688248.4 i/s - 1.36x  slower
            master_version:  1967932.3 i/s - 3.93x  slower
      
      rel key with real stuff
      master_version
      {:FREE=>-2001, :T_STRING=>2000}
      key_version
      {:FREE=>-2001, :T_STRING=>2000}
      present_version
      {:FREE=>-1001, :T_STRING=>1000}
      nil_version
      {:FREE=>-1002, :T_STRING=>1000, :T_IMEMO=>1}
      blank_version
      {:FREE=>-1001, :T_STRING=>1000}
      Warming up --------------------------------------
            master_version    93.351k i/100ms
               key_version    89.747k i/100ms
           present_version    91.963k i/100ms
               nil_version   103.370k i/100ms
             blank_version    74.845k i/100ms
      Calculating -------------------------------------
            master_version      2.179M (±21.4%) i/s -     10.362M in   5.044668s
               key_version      2.345M (± 9.8%) i/s -     11.667M in   5.030982s
           present_version      1.738M (±14.8%) i/s -      8.553M in   5.056406s
               nil_version      2.485M (±19.1%) i/s -     11.888M in   5.015940s
             blank_version      1.951M (±12.3%) i/s -      9.580M in   5.011932s
      
      Comparison:
               nil_version:  2484704.1 i/s
               key_version:  2344664.8 i/s - same-ish: difference falls within error
            master_version:  2178975.8 i/s - same-ish: difference falls within error
             blank_version:  1950532.0 i/s - same-ish: difference falls within error
           present_version:  1737866.7 i/s - 1.43x  slower
      
      rel key with nil
      master_version
      {:FREE=>-3001, :T_STRING=>3000}
      key_version
      {:FREE=>-3001, :T_STRING=>3000}
      present_version
      {:FREE=>-1}
      nil_version
      {:FREE=>-1}
      blank_version
      {:FREE=>-1}
      Warming up --------------------------------------
            master_version   112.655k i/100ms
               key_version   105.048k i/100ms
           present_version   136.219k i/100ms
               nil_version   192.026k i/100ms
             blank_version   184.846k i/100ms
      Calculating -------------------------------------
            master_version      1.893M (±12.6%) i/s -      9.238M in   5.002621s
               key_version      1.672M (±13.5%) i/s -      8.194M in   5.021197s
           present_version      4.484M (±20.5%) i/s -     21.114M in   5.002982s
               nil_version      5.294M (±18.1%) i/s -     25.155M in   5.020721s
             blank_version      5.588M (± 6.7%) i/s -     27.912M in   5.019305s
      
      Comparison:
             blank_version:  5588489.6 i/s
               nil_version:  5293929.9 i/s - same-ish: difference falls within error
           present_version:  4484493.7 i/s - same-ish: difference falls within error
            master_version:  1892919.0 i/s - 2.95x  slower
               key_version:  1672343.9 i/s - 3.34x  slower
      
      rel key with ""
      master_version
      {:FREE=>-2001, :T_STRING=>2000}
      key_version
      {:FREE=>-2001, :T_STRING=>2000}
      present_version
      {:FREE=>-1}
      nil_version
      {:FREE=>-1001, :T_STRING=>1000}
      blank_version
      {:FREE=>-1}
      Warming up --------------------------------------
            master_version   140.499k i/100ms
               key_version   124.738k i/100ms
           present_version   186.659k i/100ms
               nil_version   148.063k i/100ms
             blank_version   178.707k i/100ms
      Calculating -------------------------------------
            master_version      1.826M (±24.2%) i/s -      8.289M in   5.026603s
               key_version      1.561M (±15.3%) i/s -      7.609M in   5.005662s
           present_version      3.622M (±19.9%) i/s -     17.173M in   5.042217s
               nil_version      2.438M (±11.5%) i/s -     12.141M in   5.053335s
             blank_version      4.911M (±15.5%) i/s -     23.768M in   5.009106s
      
      Comparison:
             blank_version:  4910741.1 i/s
           present_version:  3622183.5 i/s - same-ish: difference falls within error
               nil_version:  2437606.2 i/s - 2.01x  slower
            master_version:  1825652.2 i/s - 2.69x  slower
               key_version:  1560530.5 i/s - 3.15x  slower
      ```
      d404e2cb
  4. 27 10月, 2017 1 次提交
    • D
      Prevent extra string allocations when no 'rel' arg passed · f5f0b49b
      Dillon Welch 提交于
      Do a check if the 'rel' argument is passed in, and simply set it to
      'nofollow' if 'rel' was not passed in. This prevents three string
      allocations for each call to `link_to` in that scenario. In the scenario
      where the 'rel' argument is passed in, performance is around the same as
      before as the `key?` check is very fast.
      
      ```ruby
      begin
        require "bundler/inline"
      rescue LoadError => e
        $stderr.puts "Bundler version 1.10 or later is required. Please update
                      your Bundler"
        raise e
      end
      
      gemfile(true) do
        source "https://rubygems.org"
      
        gem "benchmark-ips"
        gem "rails"
      end
      
      def allocate_count
        GC.disable
        before = ObjectSpace.count_objects
        yield
        after = ObjectSpace.count_objects
        after.each { |k,v| after[k] = v - before[k] }
        after[:T_HASH] -= 1 # probe effect - we created the before hash.
        GC.enable
        result = after.reject { |k,v| v == 0 }
        GC.start
        result
      end
      
      @hash = {}
      
      def master_version
        "#{@hash['rel'.freeze]} nofollow".lstrip
      end
      
      def fast_version
        if @hash.key?('rel'.freeze)
          "#{@hash["rel"]} nofollow".lstrip
        else
          "nofollow".freeze
        end
      end
      
      puts 'no rel key'
      
      puts "master_version"
      puts allocate_count { 1000.times { master_version } }
      puts "fast_version"
      puts allocate_count { 1000.times { fast_version } }
      
      Benchmark.ips do |x|
        x.report("master_version") { master_version }
        x.report("fast_version")     { fast_version }
        x.compare!
      end
      
      puts 'rel key'
      
      @hash['rel'] = 'hi'.freeze
      
      puts "master_version"
      puts allocate_count { 1000.times { master_version } }
      puts "fast_version"
      puts allocate_count { 1000.times { fast_version } }
      
      Benchmark.ips do |x|
        x.report("master_version") { master_version }
        x.report("fast_version")     { fast_version }
        x.compare!
      end
      ```
      
      ```
      no rel key
      master_version
      {:FREE=>-2791, :T_STRING=>3052}
      fast_version
      {:FREE=>-1}
      Warming up --------------------------------------
            master_version    80.324k i/100ms
              fast_version   200.262k i/100ms
      Calculating -------------------------------------
            master_version      2.049M (±11.9%) i/s -     10.121M in   5.025613s
              fast_version      6.645M (±21.3%) i/s -     29.439M in   5.007488s
      
      Comparison:
              fast_version:  6644506.3 i/s
            master_version:  2048833.0 i/s - 3.24x  slower
      
      rel key
      master_version
      {:FREE=>-2001, :T_STRING=>2000}
      fast_version
      {:FREE=>-2001, :T_STRING=>2000}
      Warming up --------------------------------------
            master_version   155.673k i/100ms
              fast_version   106.515k i/100ms
      Calculating -------------------------------------
            master_version      2.652M (±20.4%) i/s -     12.610M in   5.036494s
              fast_version      2.237M (±16.8%) i/s -     10.865M in   5.035366s
      
      Comparison:
            master_version:  2651702.2 i/s
              fast_version:  2237470.6 i/s - same-ish: difference falls within error
      ```
      f5f0b49b
  5. 21 10月, 2017 1 次提交
  6. 24 7月, 2017 1 次提交
  7. 02 7月, 2017 1 次提交
  8. 01 7月, 2017 2 次提交
  9. 20 6月, 2017 1 次提交
  10. 27 4月, 2017 1 次提交
  11. 19 4月, 2017 1 次提交
  12. 17 3月, 2017 1 次提交
  13. 12 1月, 2017 1 次提交
  14. 04 1月, 2017 1 次提交
  15. 24 12月, 2016 1 次提交
  16. 05 12月, 2016 1 次提交
  17. 29 10月, 2016 1 次提交
  18. 27 10月, 2016 1 次提交
    • X
      let Regexp#match? be globally available · 56832e79
      Xavier Noria 提交于
      Regexp#match? should be considered to be part of the Ruby core library. We are
      emulating it for < 2.4, but not having to require the extension is part of the
      illusion of the emulation.
      56832e79
  19. 18 10月, 2016 1 次提交
    • J
      Convert ActionController::Parameters to a hash in button_to · 4aae8bfe
      Jon Moss 提交于
      Before, an error would be raised saying that the method `to_param` was
      undefined on the instance of `ActionController::Parameters`. Now, we are
      checking to see if the `params` object being passed to `button_to`
      responds to the `permitted?` method, and if so, we will call `to_h` on it. If it
      does not respond to `permitted?`, then the `params` will remain
      unchanged.
      
      [Jon Moss, Rafael Mendonça França]
      4aae8bfe
  20. 16 8月, 2016 1 次提交
  21. 07 8月, 2016 1 次提交
  22. 25 7月, 2016 1 次提交
  23. 20 7月, 2016 1 次提交
  24. 08 3月, 2016 1 次提交
  25. 23 2月, 2016 1 次提交
  26. 22 2月, 2016 3 次提交
  27. 20 2月, 2016 1 次提交
    • J
      Fix button_to's params option to support nested names. · 459cd7fd
      James Coleman 提交于
      In e6e0579d the `params` option was added to the `button_to` helper. However, the patch doesn't support nested hashes so `{a: {b: 'c'}}` for example gets turned into a hidden form input with the name 'a' and the value being the string representation of the `{b: 'c'}` nested hash.
      
      Since Rails supports nested hashes everywhere else (and even in the URL params of link_to and button_to), I believe this to be a bug/unfinished feature.
      459cd7fd
  28. 05 1月, 2016 1 次提交
  29. 04 11月, 2015 1 次提交
  30. 06 9月, 2015 1 次提交
  31. 05 9月, 2015 1 次提交
  32. 30 7月, 2015 2 次提交
    • S
      Cut string allocations in content_tag_string · e76a8435
      schneems 提交于
      content_tag's first argument is will generate a string with an html tag so `:a` will generate: `<a></a>`. When this happens, the symbol is implicitly `to_s`-d so a new string is allocated. We can get around that by using a frozen string instead which
      
      This change buys us 74,236 bytes of memory and 1,855 fewer objects per request.
      e76a8435
    • S
      Optimize hash key · 2e95d2ef
      schneems 提交于
      No idea why on earth this hash key isn't already optimized by MRI, but it isn't. 💩
      
      This change buys us 74,077 bytes of memory and 1,852 fewer objects per request.
      2e95d2ef
  33. 24 7月, 2015 1 次提交
  34. 01 5月, 2015 1 次提交
    • Y
      Revert "Merge pull request #19844 from stevenspiel/link_to_if_block_helper_addition" · 14d0e070
      Yves Senn 提交于
      This reverts commit d459b001, reversing
      changes made to 4d4950fa.
      
      😓
      
      The block is not supposed to be passed to `link_to`. It's used for a
      customized behavior of the `condtion = false` case. The docs
      illustrate that like so:
      
      ```
      <%=
         link_to_if(@current_user.nil?, "Login", { controller: "sessions", action: "new" }) do
           link_to(@current_user.login, { controller: "accounts", action: "show", id: @current_user })
         end
      %>
      ```
      14d0e070
  35. 21 4月, 2015 1 次提交