summary refs log tree commit
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2014-10-05 07:58:16 +0000
committerEric Wong <e@80x24.org>2014-10-05 08:09:50 +0000
commit68e086d2b42ee2c9fc8017264aa353a0d543fd13 (patch)
treecd0d3f86173ae78ea1d2200d3a812d090b367b3f
parent022b0076b0eacad03eac48060198f05aa776a866 (diff)
downloadrack-68e086d2b42ee2c9fc8017264aa353a0d543fd13.tar.gz
conditionalget: avoid const lookup in case/when HEAD when-lit master
case/when dispatches already optimize away allocation of constant
string literals in all C Ruby 1.9.x/2.x releases
(ref: opt_case_dispatch in Ruby insns.def)

Other Ruby implementations presumably have similar optimizations
to encourage prettier code.

The following code snippet does not cause GC.count to increase
during the two loops, regardless of what `nr' is.
Tested on Ruby 1.9.3, 2.1.3, and trunk r47786:

    GET = "GET"
    HEAD = "HEAD"
    REQUEST_METHOD = "REQUEST_METHOD" # unnecessary in 2.2.0+
    env = { REQUEST_METHOD => "GET" }

    nr = 10000000
    nr.times do |i|
      case env[REQUEST_METHOD]
      when GET, HEAD
        :foo
      else
        :bar
      end
    end
    a = GC.count

    nr.times do |i|
      case env[REQUEST_METHOD]
      when "GET", "HEAD"
        :foo
      else
        :bar
      end
    end
    b = GC.count
    p [ a, b ]
-rw-r--r--lib/rack/conditionalget.rb2
1 files changed, 1 insertions, 1 deletions
diff --git a/lib/rack/conditionalget.rb b/lib/rack/conditionalget.rb
index 3d4c78aa..441dd382 100644
--- a/lib/rack/conditionalget.rb
+++ b/lib/rack/conditionalget.rb
@@ -21,7 +21,7 @@ module Rack
 
     def call(env)
       case env[REQUEST_METHOD]
-      when GET, HEAD
+      when "GET", "HEAD"
         status, headers, body = @app.call(env)
         headers = Utils::HeaderHash.new(headers)
         if status == 200 && fresh?(env, headers)