about summary refs log tree commit homepage
path: root/lib/yahns/http_response.rb
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2014-02-04 03:41:15 +0000
committerEric Wong <normalperson@yhbt.net>2014-02-04 03:41:15 +0000
commit648c9a67bf397c22b82496a03c4b2b2a8ae8dd1f (patch)
treeea2089a1ec7d1165231513067f6dce2eaecae79e /lib/yahns/http_response.rb
parent0fca33cc0eea24f5b6c0e8d172d59802300b7345 (diff)
downloadyahns-648c9a67bf397c22b82496a03c4b2b2a8ae8dd1f.tar.gz
If Content-Length is known, try to save some bandwidth by
corking the headers until the body is sendable.  This allows
us to avoid sending an extra packet for small HTTP responses.

This allows high-performance websites like YHBT.net to be served
faster!
Diffstat (limited to 'lib/yahns/http_response.rb')
-rw-r--r--lib/yahns/http_response.rb21
1 files changed, 20 insertions, 1 deletions
diff --git a/lib/yahns/http_response.rb b/lib/yahns/http_response.rb
index 65ecdff..e257feb 100644
--- a/lib/yahns/http_response.rb
+++ b/lib/yahns/http_response.rb
@@ -32,6 +32,20 @@ module Yahns::HttpResponse # :nodoc:
   R100_CCC = "100 Continue\r\n\r\nHTTP/1.1 "
   HTTP_EXPECT = "HTTP_EXPECT"
 
+  # no point in using one without the other, these have been in Linux
+  # for ages
+  if Socket.const_defined?(:MSG_MORE) && Socket.const_defined?(:MSG_DONTWAIT)
+    MSG_MORE = Socket::MSG_MORE
+    MSG_DONTWAIT = Socket::MSG_DONTWAIT
+  else
+    MSG_MORE = 0
+    MSG_DONTWAIT = 0
+
+    def kgio_syssend(buf, flags)
+      kgio_trywrite(buf)
+    end
+  end
+
   def response_start
     @response_start_sent ? Z : RESPONSE_START
   end
@@ -117,6 +131,7 @@ module Yahns::HttpResponse # :nodoc:
     count = hijack = nil
     k = self.class
     alive = @hs.next? && k.persistent_connections
+    flags = MSG_DONTWAIT
 
     if @hs.headers?
       buf = "#{response_start}#{status}\r\nDate: #{httpdate}\r\n"
@@ -133,6 +148,9 @@ module Yahns::HttpResponse # :nodoc:
         when %r{\AConnection\z}i
           # allow Rack apps to tell us they want to drop the client
           alive = false if value =~ /\bclose\b/i
+        when %r{\AContent-Length\z}i
+          flags |= MSG_MORE
+          buf << kv_str(key, value)
         when "rack.hijack"
           hijack = value
           body = nil # ensure we do not close body
@@ -141,10 +159,11 @@ module Yahns::HttpResponse # :nodoc:
         end
       end
       buf << (alive ? CONN_KA : CONN_CLOSE)
-      case rv = kgio_trywrite(buf)
+      case rv = kgio_syssend(buf, flags)
       when nil # all done, likely
         break
       when String
+        flags = MSG_DONTWAIT
         buf = rv # hope the skb grows
       when :wait_writable, :wait_readable
         if k.output_buffering