• 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
url_helper.rb 28.7 KB