提交 c57e914c 编写于 作者: D Dillon Welch

Performance improvements for add_method_to_attributes!

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
```
上级 daf77db6
......@@ -589,7 +589,7 @@ def link_to_remote_options?(options)
end
def add_method_to_attributes!(html_options, method)
if method && method.to_s.downcase != "get" && html_options["rel"] !~ /nofollow/
if method_not_get_method?(method) && html_options["rel"] !~ /nofollow/
if html_options["rel"].blank?
html_options["rel"] = "nofollow"
else
......@@ -599,6 +599,19 @@ def add_method_to_attributes!(html_options, method)
html_options["data-method"] = 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
def token_tag(token = nil, form_options: {})
if token != false && protect_against_forgery?
token ||= form_authenticity_token(form_options: form_options)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册