* [PATCH 0/5] a few more odds and ends before 5.0
@ 2015-11-21 8:52 Eric Wong
2015-11-21 8:52 ` [PATCH 1/5] tiny bytecode reductions for cold paths Eric Wong
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Eric Wong @ 2015-11-21 8:52 UTC (permalink / raw)
To: rainbows-public
A few more odds and ends before 5.0 (sometime next week).
I'll do some more testing later, but overall keeping this up-to-date
with the latest developments in unicorn isn't as bad as I thought it'd
be.
5 more changes:
tiny bytecode reductions for cold paths
Ruby 1.9.3+-only cleanups
response: avoid garbage string entirely
revactor: remove fcntl dependency
response: simplify regexp
bin/rainbows | 6 +++---
lib/rainbows.rb | 5 ++---
lib/rainbows/configurator.rb | 16 ++++++++--------
lib/rainbows/coolio.rb | 9 ++-------
lib/rainbows/coolio/heartbeat.rb | 2 +-
lib/rainbows/epoll/client.rb | 5 ++---
lib/rainbows/fiber/base.rb | 2 +-
lib/rainbows/http_server.rb | 4 ++--
lib/rainbows/response.rb | 10 +++++-----
lib/rainbows/revactor.rb | 1 -
lib/rainbows/revactor/client.rb | 3 +--
lib/rainbows/stream_response_epoll.rb | 2 +-
lib/rainbows/writer_thread_pool.rb | 4 ++--
lib/rainbows/xepoll_thread_pool/client.rb | 3 +--
lib/rainbows/xepoll_thread_spawn/client.rb | 3 +--
15 files changed, 32 insertions(+), 43 deletions(-)
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/5] tiny bytecode reductions for cold paths
2015-11-21 8:52 [PATCH 0/5] a few more odds and ends before 5.0 Eric Wong
@ 2015-11-21 8:52 ` Eric Wong
2015-11-21 8:52 ` [PATCH 2/5] Ruby 1.9.3+-only cleanups Eric Wong
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Eric Wong @ 2015-11-21 8:52 UTC (permalink / raw)
To: rainbows-public
Less code in cold paths can improve speed for hot paths.
Single-byte strings for String#split is optimized in mainline Ruby,
so it's not actually a performance loss for sendfile_range in
response.rb
Regexps are at least 400 bytes each, so prefer non-Regexps
if possible, especially for cold sites where performance does
not matter.
---
lib/rainbows/http_server.rb | 4 ++--
lib/rainbows/response.rb | 4 ++--
lib/rainbows/stream_response_epoll.rb | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/lib/rainbows/http_server.rb b/lib/rainbows/http_server.rb
index 429539c..33bb96c 100644
--- a/lib/rainbows/http_server.rb
+++ b/lib/rainbows/http_server.rb
@@ -82,10 +82,10 @@ def svc
end
def use=(mod)
- @use = mod.to_s.split(/::/)[-1].to_sym
+ @use = mod.to_s.split('::')[-1].to_sym
new_defaults = {
'rainbows.model' => @use,
- 'rack.multithread' => !!(mod.to_s =~ /Thread/),
+ 'rack.multithread' => mod.to_s.include?('Thread'),
'rainbows.autochunk' => [:Coolio,:Rev,:Epoll,:XEpoll,
:EventMachine,:NeverBlock].include?(@use),
}
diff --git a/lib/rainbows/response.rb b/lib/rainbows/response.rb
index 0b5e542..9bbea81 100644
--- a/lib/rainbows/response.rb
+++ b/lib/rainbows/response.rb
@@ -40,7 +40,7 @@ def write_headers(status, headers, alive, body)
else
if /\n/ =~ value
# avoiding blank, key-only cookies with /\n+/
- buf << value.split(/\n+/).map! { |v| "#{key}: #{v}\r\n" }.join
+ value.split(/\n+/).each { |v| buf << "#{key}: #{v}\r\n" }
else
buf << "#{key}: #{value}\r\n"
end
@@ -151,7 +151,7 @@ def sendfile_range(status, headers)
200 == status &&
/\Abytes=(\d+-\d*|\d*-\d+)\z/ =~ @hp.env['HTTP_RANGE'] or
return
- a, b = $1.split(/-/)
+ a, b = $1.split('-'.freeze)
# HeaderHash is quite expensive, and Rack::File currently
# uses a regular Ruby Hash with properly-cased headers the
diff --git a/lib/rainbows/stream_response_epoll.rb b/lib/rainbows/stream_response_epoll.rb
index 7c2f4f6..48ef298 100644
--- a/lib/rainbows/stream_response_epoll.rb
+++ b/lib/rainbows/stream_response_epoll.rb
@@ -39,7 +39,7 @@ def http_response_write(socket, status, headers, body)
else
if /\n/ =~ value
# avoiding blank, key-only cookies with /\n+/
- buf << value.split(/\n+/).map! { |v| "#{key}: #{v}\r\n" }.join
+ value.split(/\n+/).each { |v| buf << "#{key}: #{v}\r\n" }
else
buf << "#{key}: #{value}\r\n"
end
--
EW
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/5] Ruby 1.9.3+-only cleanups
2015-11-21 8:52 [PATCH 0/5] a few more odds and ends before 5.0 Eric Wong
2015-11-21 8:52 ` [PATCH 1/5] tiny bytecode reductions for cold paths Eric Wong
@ 2015-11-21 8:52 ` Eric Wong
2015-11-21 8:52 ` [PATCH 3/5] response: avoid garbage string entirely Eric Wong
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Eric Wong @ 2015-11-21 8:52 UTC (permalink / raw)
To: rainbows-public
unicorn 5 will only support Ruby 1.9.3 and later, so remove
some checks for Hash#compare_by_identity and IO.copy_stream
which we know exist in Ruby 1.9.
Favor &:sym proc dispatch to avoid unnecessary captures and
bytecode size increases, too.
Finally, ensure we fail fast by converting some literal
hashes to use non-arrow syntax for symbolic keys.
---
bin/rainbows | 6 +++---
lib/rainbows.rb | 5 ++---
lib/rainbows/configurator.rb | 16 ++++++++--------
lib/rainbows/coolio.rb | 9 ++-------
lib/rainbows/coolio/heartbeat.rb | 2 +-
lib/rainbows/epoll/client.rb | 5 ++---
lib/rainbows/fiber/base.rb | 2 +-
lib/rainbows/writer_thread_pool.rb | 4 ++--
lib/rainbows/xepoll_thread_pool/client.rb | 3 +--
lib/rainbows/xepoll_thread_spawn/client.rb | 3 +--
10 files changed, 23 insertions(+), 32 deletions(-)
diff --git a/bin/rainbows b/bin/rainbows
index f5ddaa7..c659afa 100755
--- a/bin/rainbows
+++ b/bin/rainbows
@@ -117,9 +117,9 @@
if $DEBUG
require 'pp'
pp({
- :unicorn_options => options,
- :app => app,
- :daemonize => rackup_opts[:daemonize],
+ unicorn_options: options,
+ app: app,
+ daemonize: rackup_opts[:daemonize],
})
end
diff --git a/lib/rainbows.rb b/lib/rainbows.rb
index f23b387..6e7e4f2 100644
--- a/lib/rainbows.rb
+++ b/lib/rainbows.rb
@@ -11,8 +11,7 @@ module Rainbows
# map of numeric file descriptors to IO objects to avoid using IO.new
# and potentially causing race conditions when using /dev/fd/
- FD_MAP = {}
- FD_MAP.compare_by_identity if FD_MAP.respond_to?(:compare_by_identity)
+ FD_MAP = {}.compare_by_identity
require 'rainbows/const'
require 'rainbows/http_parser'
@@ -92,7 +91,7 @@ def self.quit!
tmp = @readers.dup
@readers.clear
tmp.each { |s| s.close rescue nil }.clear
- @at_quit.each { |task| task.call }
+ @at_quit.each(&:call)
# XXX hack to break out of IO.select in worker_loop for some models
Process.kill(:QUIT, $$)
diff --git a/lib/rainbows/configurator.rb b/lib/rainbows/configurator.rb
index 92dacd6..73820a1 100644
--- a/lib/rainbows/configurator.rb
+++ b/lib/rainbows/configurator.rb
@@ -21,14 +21,14 @@
# stdout_path "/path/to/output.log"
module Rainbows::Configurator
Unicorn::Configurator::DEFAULTS.merge!({
- :use => Rainbows::Base,
- :worker_connections => 50,
- :keepalive_timeout => 5,
- :keepalive_requests => 100,
- :client_max_body_size => 1024 * 1024,
- :client_header_buffer_size => 1024,
- :client_max_header_size => 112 * 1024,
- :copy_stream => IO.respond_to?(:copy_stream) ? IO : false,
+ use: Rainbows::Base,
+ worker_connections: 50,
+ keepalive_timeout: 5,
+ keepalive_requests: 100,
+ client_max_body_size: 1024 * 1024,
+ client_header_buffer_size: 1024,
+ client_max_header_size: 112 * 1024,
+ copy_stream: IO,
})
# Configures \Rainbows! with a given concurrency model to +use+ and
diff --git a/lib/rainbows/coolio.rb b/lib/rainbows/coolio.rb
index a993060..2aba3ea 100644
--- a/lib/rainbows/coolio.rb
+++ b/lib/rainbows/coolio.rb
@@ -27,15 +27,10 @@
module Rainbows::Coolio
# :stopdoc:
# keep-alive timeout scoreboard
- KATO = {}
+ KATO = {}.compare_by_identity
# all connected clients
- CONN = {}
-
- if {}.respond_to?(:compare_by_identity)
- CONN.compare_by_identity
- KATO.compare_by_identity
- end
+ CONN = {}.compare_by_identity
autoload :Client, 'rainbows/coolio/client'
autoload :Master, 'rainbows/coolio/master'
diff --git a/lib/rainbows/coolio/heartbeat.rb b/lib/rainbows/coolio/heartbeat.rb
index fcfbb0f..adea248 100644
--- a/lib/rainbows/coolio/heartbeat.rb
+++ b/lib/rainbows/coolio/heartbeat.rb
@@ -9,7 +9,7 @@ class Rainbows::Coolio::Heartbeat < Coolio::TimerWatcher
KATO = Rainbows::Coolio::KATO
CONN = Rainbows::Coolio::CONN
Rainbows.config!(self, :keepalive_timeout)
- Rainbows.at_quit { KATO.each_key { |client| client.timeout? }.clear }
+ Rainbows.at_quit { KATO.each_key(&:timeout?).clear }
def on_timer
if (ot = KEEPALIVE_TIMEOUT) >= 0
diff --git a/lib/rainbows/epoll/client.rb b/lib/rainbows/epoll/client.rb
index fe04258..85e504c 100644
--- a/lib/rainbows/epoll/client.rb
+++ b/lib/rainbows/epoll/client.rb
@@ -9,9 +9,8 @@ module Rainbows::Epoll::Client
IN = SleepyPenguin::Epoll::IN | SleepyPenguin::Epoll::ONESHOT
OUT = SleepyPenguin::Epoll::OUT | SleepyPenguin::Epoll::ONESHOT
EPINOUT = IN | OUT
- KATO = {}
- KATO.compare_by_identity if KATO.respond_to?(:compare_by_identity)
- Rainbows.at_quit { KATO.each_key { |k| k.timeout! }.clear }
+ KATO = {}.compare_by_identity
+ Rainbows.at_quit { KATO.each_key(&:timeout!).clear }
Rainbows.config!(self, :keepalive_timeout)
EP = Rainbows::EP
@@last_expire = Rainbows.now
diff --git a/lib/rainbows/fiber/base.rb b/lib/rainbows/fiber/base.rb
index 7c4fb59..a3c098a 100644
--- a/lib/rainbows/fiber/base.rb
+++ b/lib/rainbows/fiber/base.rb
@@ -50,7 +50,7 @@ def schedule_sleepers
false
end
}
- fibs.each { |fib| fib.resume }
+ fibs.each(&:resume)
max_sleep = 1.0 # wake up semi-frequently to prevent SIGKILL from master
if max
diff --git a/lib/rainbows/writer_thread_pool.rb b/lib/rainbows/writer_thread_pool.rb
index b5688e0..657d076 100644
--- a/lib/rainbows/writer_thread_pool.rb
+++ b/lib/rainbows/writer_thread_pool.rb
@@ -50,9 +50,9 @@ def worker_loop(worker) # :nodoc:
end
end
- @@q = qp.map { |q| q.queue }
+ @@q = qp.map(&:queue)
super(worker) # accept loop from Unicorn
- qp.each { |q| q.quit! }
+ qp.each(&:quit!)
end
# :startdoc:
end
diff --git a/lib/rainbows/xepoll_thread_pool/client.rb b/lib/rainbows/xepoll_thread_pool/client.rb
index 760bbde..ca62727 100644
--- a/lib/rainbows/xepoll_thread_pool/client.rb
+++ b/lib/rainbows/xepoll_thread_pool/client.rb
@@ -38,8 +38,7 @@ def self.app_run(queue)
ep = SleepyPenguin::Epoll
EP = ep.new
IN = ep::IN | ep::ONESHOT
- KATO = {}
- KATO.compare_by_identity if KATO.respond_to?(:compare_by_identity)
+ KATO = {}.compare_by_identity
LOCK = Mutex.new
Rainbows.at_quit do
clients = nil
diff --git a/lib/rainbows/xepoll_thread_spawn/client.rb b/lib/rainbows/xepoll_thread_spawn/client.rb
index 67c5976..218db3e 100644
--- a/lib/rainbows/xepoll_thread_spawn/client.rb
+++ b/lib/rainbows/xepoll_thread_spawn/client.rb
@@ -27,8 +27,7 @@ def self.included(klass) # included in Rainbows::Client
ep = SleepyPenguin::Epoll
EP = ep.new
IN = ep::IN | ep::ONESHOT
- KATO = {}
- KATO.compare_by_identity if KATO.respond_to?(:compare_by_identity)
+ KATO = {}.compare_by_identity
LOCK = Mutex.new
Rainbows.at_quit do
clients = nil
--
EW
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 3/5] response: avoid garbage string entirely
2015-11-21 8:52 [PATCH 0/5] a few more odds and ends before 5.0 Eric Wong
2015-11-21 8:52 ` [PATCH 1/5] tiny bytecode reductions for cold paths Eric Wong
2015-11-21 8:52 ` [PATCH 2/5] Ruby 1.9.3+-only cleanups Eric Wong
@ 2015-11-21 8:52 ` Eric Wong
2015-11-21 8:52 ` [PATCH 4/5] revactor: remove fcntl dependency Eric Wong
2015-11-21 8:52 ` [PATCH 5/5] response: simplify regexp Eric Wong
4 siblings, 0 replies; 6+ messages in thread
From: Eric Wong @ 2015-11-21 8:52 UTC (permalink / raw)
To: rainbows-public
Even in frozen string literals enabled in Ruby 2.3.0dev,
dstrings still create garbage as the optimizer is
not yet smart enough to optimize it despite the limited
choice of internals being known.
Maybe in the future Ruby will be smart enough, but not yet...
---
lib/rainbows/response.rb | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/rainbows/response.rb b/lib/rainbows/response.rb
index 9bbea81..ac50321 100644
--- a/lib/rainbows/response.rb
+++ b/lib/rainbows/response.rb
@@ -46,8 +46,8 @@ def write_headers(status, headers, alive, body)
end
end
end
- write(buf << "Connection: #{alive ? 'keep-alive'.freeze
- : 'close'.freeze}\r\n\r\n")
+ write(buf << (alive ? "Connection: keep-alive\r\n\r\n".freeze
+ : "Connection: close\r\n\r\n".freeze))
if hijack
body = nil # ensure caller does not close body
--
EW
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 4/5] revactor: remove fcntl dependency
2015-11-21 8:52 [PATCH 0/5] a few more odds and ends before 5.0 Eric Wong
` (2 preceding siblings ...)
2015-11-21 8:52 ` [PATCH 3/5] response: avoid garbage string entirely Eric Wong
@ 2015-11-21 8:52 ` Eric Wong
2015-11-21 8:52 ` [PATCH 5/5] response: simplify regexp Eric Wong
4 siblings, 0 replies; 6+ messages in thread
From: Eric Wong @ 2015-11-21 8:52 UTC (permalink / raw)
To: rainbows-public
In the unlikely case somebody runs revactor, they won't need to
load the extra fcntl.so library into their process anymore.
In retrospect, we could've alway used IO#close_on_exec= since
it appeared in 1.9.1 and (IIRC) revactor always required 1.9.1+
---
lib/rainbows/revactor.rb | 1 -
lib/rainbows/revactor/client.rb | 3 +--
2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/lib/rainbows/revactor.rb b/lib/rainbows/revactor.rb
index e68fee6..fae5f16 100644
--- a/lib/rainbows/revactor.rb
+++ b/lib/rainbows/revactor.rb
@@ -1,6 +1,5 @@
# -*- encoding: binary -*-
require 'revactor'
-require 'fcntl'
Revactor::VERSION >= '0.1.5' or abort 'revactor 0.1.5 is required'
# Enables use of the Actor model through {Revactor}[http://revactor.org]
diff --git a/lib/rainbows/revactor/client.rb b/lib/rainbows/revactor/client.rb
index c1cb7aa..5b1e52d 100644
--- a/lib/rainbows/revactor/client.rb
+++ b/lib/rainbows/revactor/client.rb
@@ -1,6 +1,5 @@
# -*- encoding: binary -*-
# :enddoc:
-require 'fcntl'
class Rainbows::Revactor::Client
autoload :TeeSocket, 'rainbows/revactor/client/tee_socket'
RD_ARGS = {}
@@ -11,7 +10,7 @@ class Rainbows::Revactor::Client
def initialize(client)
@client, @rd_args, @ts = client, [ nil ], nil
io = client.instance_variable_get(:@_io)
- io.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
+ io.close_on_exec = true
@kgio_addr = if Revactor::TCP::Socket === client
@rd_args << RD_ARGS
client.remote_addr
--
EW
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 5/5] response: simplify regexp
2015-11-21 8:52 [PATCH 0/5] a few more odds and ends before 5.0 Eric Wong
` (3 preceding siblings ...)
2015-11-21 8:52 ` [PATCH 4/5] revactor: remove fcntl dependency Eric Wong
@ 2015-11-21 8:52 ` Eric Wong
4 siblings, 0 replies; 6+ messages in thread
From: Eric Wong @ 2015-11-21 8:52 UTC (permalink / raw)
To: rainbows-public
Redundant \z statements are ugly and wastes 4 bytes on x86-64
according to ObjectSpace.memsize_of
---
lib/rainbows/response.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/rainbows/response.rb b/lib/rainbows/response.rb
index ac50321..62dfa39 100644
--- a/lib/rainbows/response.rb
+++ b/lib/rainbows/response.rb
@@ -30,7 +30,7 @@ def write_headers(status, headers, alive, body)
"Date: #{httpdate}\r\n"
headers.each do |key, value|
case key
- when %r{\A(?:Date\z|Connection\z)}i
+ when %r{\A(?:Date|Connection)\z}i
next
when "rack.hijack"
# this was an illegal key in Rack < 1.5, so it should be
--
EW
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2015-11-21 8:52 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-21 8:52 [PATCH 0/5] a few more odds and ends before 5.0 Eric Wong
2015-11-21 8:52 ` [PATCH 1/5] tiny bytecode reductions for cold paths Eric Wong
2015-11-21 8:52 ` [PATCH 2/5] Ruby 1.9.3+-only cleanups Eric Wong
2015-11-21 8:52 ` [PATCH 3/5] response: avoid garbage string entirely Eric Wong
2015-11-21 8:52 ` [PATCH 4/5] revactor: remove fcntl dependency Eric Wong
2015-11-21 8:52 ` [PATCH 5/5] response: simplify regexp Eric Wong
Code repositories for project(s) associated with this public inbox
https://yhbt.net/rainbows.git/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).