summary refs log tree commit
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2009-12-10 21:33:53 -0600
committerJoshua Peek <josh@joshpeek.com>2009-12-10 21:33:53 -0600
commitcdf13618445fa7065c07d62b115907856d6d1095 (patch)
treea0b6b919f56f6b8b30bc5dc7b54b401e26a32a9e
parenta9440bc752be9b3093669614c6b56bf78d592958 (diff)
downloadrack-cdf13618445fa7065c07d62b115907856d6d1095.tar.gz
HeaderHash.new avoids unnecessary object creation
Creating a new HeaderHash is an O(n) operation in addition to
the cost of allocating a new object.  When using multiple pieces
of middleware, this can lead to unnecessary memory allocation
and iteration overhead.   We now explicitly define the
HeaderHash.new class method to return its original argument if
it is already a HeaderHash to avoid repeating work.

Signed-off-by: Joshua Peek <josh@joshpeek.com>
-rw-r--r--lib/rack/utils.rb4
-rw-r--r--test/spec_rack_utils.rb8
2 files changed, 12 insertions, 0 deletions
diff --git a/lib/rack/utils.rb b/lib/rack/utils.rb
index b5aa8a19..4956177e 100644
--- a/lib/rack/utils.rb
+++ b/lib/rack/utils.rb
@@ -263,6 +263,10 @@ module Rack
     # A case-insensitive Hash that preserves the original case of a
     # header when set.
     class HeaderHash < Hash
+      def self.new(hash={})
+        HeaderHash === hash ? hash : super(hash)
+      end
+
       def initialize(hash={})
         super()
         @names = {}
diff --git a/test/spec_rack_utils.rb b/test/spec_rack_utils.rb
index 0a73d18c..755a1619 100644
--- a/test/spec_rack_utils.rb
+++ b/test/spec_rack_utils.rb
@@ -273,6 +273,14 @@ context "Rack::Utils::HeaderHash" do
     h = Rack::Utils::HeaderHash.new("foo" => "bar")
     h.delete("Hello").should.be.nil
   end
+
+  specify "should avoid unnecessary object creation if possible" do
+    a = Rack::Utils::HeaderHash.new("foo" => "bar")
+    b = Rack::Utils::HeaderHash.new(a)
+    b.object_id.should.equal(a.object_id)
+    b.should.equal(a)
+  end
+
 end
 
 context "Rack::Utils::Context" do