diff options
author | Eric Wong <normalperson@yhbt.net> | 2014-02-04 03:41:15 +0000 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2014-02-04 03:41:15 +0000 |
commit | 648c9a67bf397c22b82496a03c4b2b2a8ae8dd1f (patch) | |
tree | ea2089a1ec7d1165231513067f6dce2eaecae79e | |
parent | 0fca33cc0eea24f5b6c0e8d172d59802300b7345 (diff) | |
download | yahns-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!
-rw-r--r-- | lib/yahns/http_response.rb | 21 | ||||
-rw-r--r-- | test/server_helper.rb | 5 | ||||
-rw-r--r-- | yahns.gemspec | 2 |
3 files changed, 26 insertions, 2 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 diff --git a/test/server_helper.rb b/test/server_helper.rb index d4b8f98..a92a2da 100644 --- a/test/server_helper.rb +++ b/test/server_helper.rb @@ -100,4 +100,9 @@ module TrywriteBlocked return :wait_writable if $_tw_block_on.include?($_tw_blocked += 1) super end + + def kgio_syssend(*args) + return :wait_writable if $_tw_block_on.include?($_tw_blocked += 1) + super + end end diff --git a/yahns.gemspec b/yahns.gemspec index 200230f..26b68b2 100644 --- a/yahns.gemspec +++ b/yahns.gemspec @@ -10,7 +10,7 @@ Gem::Specification.new do |s| s.email = %q{yahns@yhbt.net} s.executables = manifest.grep(%r{\Abin/}).map { |s| s.sub(%r{\Abin/}, "") } s.files = manifest - s.add_dependency(%q<kgio>, '~> 2.8') + s.add_dependency(%q<kgio>, '~> 2.9') s.add_dependency(%q<sleepy_penguin>, '~> 3.2') s.add_dependency(%q<sendfile>, '~> 1.2.1') s.add_dependency(%q<unicorn>, '~> 4.6', '>= 4.6.3') |