aboutsummaryrefslogtreecommitdiffstats
path: root/actionview
diff options
context:
space:
mode:
authorDillon Welch <daw0328@gmail.com>2017-10-26 18:17:38 -0700
committerDillon Welch <daw0328@gmail.com>2017-10-26 18:19:14 -0700
commitf5f0b49b9b233f85664d7a464c18afb2f3f10692 (patch)
treeee37f2c3e4cea0e8de47c950db39c223637fd2c7 /actionview
parent432b193d3a21540e29b9a2f381ac6d38ae2bfeb2 (diff)
downloadrails-f5f0b49b9b233f85664d7a464c18afb2f3f10692.tar.gz
rails-f5f0b49b9b233f85664d7a464c18afb2f3f10692.tar.bz2
rails-f5f0b49b9b233f85664d7a464c18afb2f3f10692.zip
Prevent extra string allocations when no 'rel' arg passed
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 ```
Diffstat (limited to 'actionview')
-rw-r--r--actionview/lib/action_view/helpers/url_helper.rb10
1 files changed, 7 insertions, 3 deletions
diff --git a/actionview/lib/action_view/helpers/url_helper.rb b/actionview/lib/action_view/helpers/url_helper.rb
index efda549c0d..4e436433c4 100644
--- a/actionview/lib/action_view/helpers/url_helper.rb
+++ b/actionview/lib/action_view/helpers/url_helper.rb
@@ -589,10 +589,14 @@ module ActionView
end
def add_method_to_attributes!(html_options, method)
- if method && method.to_s.downcase != "get".freeze && html_options["rel".freeze] !~ /nofollow/
- html_options["rel".freeze] = "#{html_options["rel".freeze]} nofollow".lstrip
+ if method && method.to_s.downcase != "get" && html_options["rel"] !~ /nofollow/
+ if html_options.key?("rel")
+ html_options["rel"] = "#{html_options["rel"]} nofollow".lstrip
+ else
+ html_options["rel"] = "nofollow"
+ end
end
- html_options["data-method".freeze] = method
+ html_options["data-method"] = method
end
def token_tag(token = nil, form_options: {})