* [ANN] Rainbows! 5.0.0 - Rack HTTP server for the sleepy
@ 2015-11-25 1:04 6% Eric Wong
0 siblings, 0 replies; 3+ results
From: Eric Wong @ 2015-11-25 1:04 UTC (permalink / raw)
To: ruby-talk; +Cc: rainbows-public
Rainbows! is an HTTP server for sleepy Rack applications.
While it will be maintained as long as anybody uses it,
use of Rainbows! for new projects is not recommended,
try other servers instead:
http://bogomips.org/rainbows-public/20151020095934.GA19114@dcvr.yhbt.net/
Rainbows! 5.0.0 - maintained as long as anybody uses it!
This release syncs with unicorn 5 and drops some old compatibility
cruft from old releases. Performance should be roughly unchanged
for Ruby 2.2 users while older Rubies (1.9.3 - 2.1) will see
minor, probably unnoticeable performance regressions.
Compatibility:
* The horrible, proprietary (:P) "Status:" response header is
finally gone, saving at least 16 precious bytes in every HTTP
response. This should make it easier to write custom HTTP clients
which are compatible across all HTTP servers. It will hopefully
make migrating between different Rack servers easier for new
projects.
* Ruby 1.8 support removed. Ruby 1.9.3 is currently the earliest
supported version. However, expect minor, likely-unnoticeable
performance regressions if you use Ruby 2.1 or earlier. Going
forward, Rainbows! will favor the latest version (currently 2.2) of
the mainline Ruby implementation, potentially sacrificing
performance on older Rubies.
New features:
* sd_listen_fds(3) emulation added for systemd compatibility.
You may now stop using PID files and other process monitoring
software when using systemd.
* Newly-set TCP socket options are now applied to inherited sockets.
* Dynamic changes in the application to Rack::Utils::HTTP_STATUS
hash is now supported; allowing users to set custom status lines
in Rack to be reflected in unicorn. This feature causes a minor
performance regression, but is made up for Ruby 2.2 users with
other optimizations.
* The monotonic clock is used under Ruby 2.1+, making the
timeout feature immune to system clock changes.
As Rainbows! may be used anonymously without registration, the
project is committed to supporting anonymous and pseudonymous
help requests, contributions and feedback via plain-text mail to:
rainbows-public@bogomips.org
The mail submission port (587) is open to those behind firewalls
and allows access via Tor and anonymous remailers.
Archives are accessible via:
* http://bogomips.org/rainbows-public/
* nntp://news.public-inbox.org/inbox.comp.lang.ruby.rainbows
* nntp://news.gmane.org/gmane.comp.lang.ruby.rainbows.general
and mirrored to various other places, so you do not even need
to use a valid address when posting.
18 changes since Rainbows! 4.7.0
README: remove Zbatery references
http_parser: handle keepalive_requests internally
kill the moronic Status: header
reflect changes in Rack::Utils::HTTP_STATUS_CODES
reduce constant lookup dependencies
http_parser: workaround hijack changes in unicorn 5
http_server: add master_pid attribute
stream_response_epoll: remove hijack_prepare call
bump to unicorn 5.0.1, use monotonic clock
add .gitattributes for Ruby method detection
response: avoid garbage string entirely
tiny bytecode reductions for cold paths
Ruby 1.9.3+-only cleanups
revactor: remove fcntl dependency
response: simplify regexp
t0105: fix test reliability
fix Rainbows.now definition for old Rubies
fix broken constant lookups in unmaintained bits
* http://rainbows.bogomips.org/
* rainbows-public@bogomips.org
* http://bogomips.org/rainbows-public/
* git clone git://bogomips.org/rainbows.git
* http://rainbows.bogomips.org/NEWS.atom.xml
*zzzzzzzz*
^ permalink raw reply [relevance 6%]
* [PATCH 3/3] bump to unicorn 5.0.1, use monotonic clock
2015-11-18 3:58 7% [PATCH 0/3] final round of changes for unicorn 5 compatibility Eric Wong
@ 2015-11-18 3:58 4% ` Eric Wong
0 siblings, 0 replies; 3+ results
From: Eric Wong @ 2015-11-18 3:58 UTC (permalink / raw)
To: rainbows-public
The timeout (mis)feature in unicorn uses the monotonic clock
if available. We must follow suit to avoid having our timeout
functionality completely broken.
---
lib/rainbows.rb | 19 ++++++++++++++++---
lib/rainbows/coolio/client.rb | 2 +-
lib/rainbows/coolio/heartbeat.rb | 2 +-
lib/rainbows/epoll/client.rb | 4 ++--
lib/rainbows/fiber.rb | 2 +-
lib/rainbows/fiber/base.rb | 4 ++--
lib/rainbows/fiber/coolio/heartbeat.rb | 2 +-
lib/rainbows/fiber/io.rb | 2 +-
lib/rainbows/join_threads.rb | 4 ++--
lib/rainbows/process_client.rb | 4 ++--
lib/rainbows/thread_timeout.rb | 8 ++++----
lib/rainbows/xepoll_thread_pool/client.rb | 4 ++--
lib/rainbows/xepoll_thread_spawn/client.rb | 4 ++--
rainbows.gemspec | 2 +-
t/test_isolate.rb | 2 +-
15 files changed, 39 insertions(+), 26 deletions(-)
diff --git a/lib/rainbows.rb b/lib/rainbows.rb
index 0af5620..f23b387 100644
--- a/lib/rainbows.rb
+++ b/lib/rainbows.rb
@@ -75,8 +75,8 @@ module Rainbows
end
def self.tick
- @worker.tick = Time.now.to_i
- exit!(2) if @expire && Time.now >= @expire
+ @worker.tick = now.to_i
+ exit!(2) if @expire && now >= @expire
@alive && @server.master_pid == Process.ppid or quit!
end
@@ -88,7 +88,7 @@ module Rainbows
unless @expire
@alive = false
Rainbows::HttpParser.quit
- @expire = Time.now + (@server.timeout * 2.0)
+ @expire = now + (@server.timeout * 2.0)
tmp = @readers.dup
@readers.clear
tmp.each { |s| s.close rescue nil }.clear
@@ -100,6 +100,19 @@ module Rainbows
false
end
+ # try to use the monotonic clock in Ruby >= 2.1, it is immune to clock
+ # offset adjustments and generates less garbage (Float vs Time object)
+ begin
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ def self.now
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ end
+ rescue NameError, NoMethodError
+ def self.now # Ruby <= 2.0
+ Rainbows.now
+ end
+ end
+
autoload :Base, "rainbows/base"
autoload :WriterThreadPool, "rainbows/writer_thread_pool"
autoload :WriterThreadSpawn, "rainbows/writer_thread_spawn"
diff --git a/lib/rainbows/coolio/client.rb b/lib/rainbows/coolio/client.rb
index ad827f6..cd22c22 100644
--- a/lib/rainbows/coolio/client.rb
+++ b/lib/rainbows/coolio/client.rb
@@ -154,7 +154,7 @@ class Rainbows::Coolio::Client < Coolio::IO
# buf == :wait_readable
unless enabled?
enable
- KATO[self] = Time.now
+ KATO[self] = Rainbows.now
end
else
on_read(''.freeze)
diff --git a/lib/rainbows/coolio/heartbeat.rb b/lib/rainbows/coolio/heartbeat.rb
index 3ae9e16..fcfbb0f 100644
--- a/lib/rainbows/coolio/heartbeat.rb
+++ b/lib/rainbows/coolio/heartbeat.rb
@@ -13,7 +13,7 @@ class Rainbows::Coolio::Heartbeat < Coolio::TimerWatcher
def on_timer
if (ot = KEEPALIVE_TIMEOUT) >= 0
- ot = Time.now - ot
+ ot = Rainbows.now - ot
KATO.delete_if { |client, time| time < ot and client.timeout? }
end
exit if (! Rainbows.tick && CONN.size <= 0)
diff --git a/lib/rainbows/epoll/client.rb b/lib/rainbows/epoll/client.rb
index 6dcbb81..fe04258 100644
--- a/lib/rainbows/epoll/client.rb
+++ b/lib/rainbows/epoll/client.rb
@@ -14,10 +14,10 @@ module Rainbows::Epoll::Client
Rainbows.at_quit { KATO.each_key { |k| k.timeout! }.clear }
Rainbows.config!(self, :keepalive_timeout)
EP = Rainbows::EP
- @@last_expire = Time.now
+ @@last_expire = Rainbows.now
def self.expire
- return if ((now = Time.now) - @@last_expire) < 1.0
+ return if ((now = Rainbows.now) - @@last_expire) < 1.0
if (ot = KEEPALIVE_TIMEOUT) >= 0
ot = now - ot
KATO.delete_if { |client, time| time < ot and client.timeout! }
diff --git a/lib/rainbows/fiber.rb b/lib/rainbows/fiber.rb
index a0f3f99..a37512f 100644
--- a/lib/rainbows/fiber.rb
+++ b/lib/rainbows/fiber.rb
@@ -29,7 +29,7 @@ module Rainbows::Fiber
# right?). Calling this directly is deprecated, use
# Rainbows.sleep(seconds) instead.
def self.sleep(seconds)
- ZZ[Fiber.current] = Time.now + seconds
+ ZZ[Fiber.current] = Rainbows.now + seconds
Fiber.yield
end
diff --git a/lib/rainbows/fiber/base.rb b/lib/rainbows/fiber/base.rb
index e8f5b16..7c4fb59 100644
--- a/lib/rainbows/fiber/base.rb
+++ b/lib/rainbows/fiber/base.rb
@@ -40,7 +40,7 @@ module Rainbows::Fiber::Base
# woken and returns an interval to IO.select on
def schedule_sleepers
max = nil
- now = Time.now
+ now = Rainbows.now
fibs = []
ZZ.delete_if { |fib, time|
if now >= time
@@ -54,7 +54,7 @@ module Rainbows::Fiber::Base
max_sleep = 1.0 # wake up semi-frequently to prevent SIGKILL from master
if max
- max -= Time.now
+ max -= Rainbows.now
return 0 if max < 0.0
return max_sleep if max > max_sleep
max
diff --git a/lib/rainbows/fiber/coolio/heartbeat.rb b/lib/rainbows/fiber/coolio/heartbeat.rb
index 6b1e4f9..7014dbe 100644
--- a/lib/rainbows/fiber/coolio/heartbeat.rb
+++ b/lib/rainbows/fiber/coolio/heartbeat.rb
@@ -5,7 +5,7 @@ class Rainbows::Fiber::Coolio::Heartbeat < Coolio::TimerWatcher
ZZ = Rainbows::Fiber::ZZ
def on_timer
exit if (! Rainbows.tick && Rainbows.cur <= 0)
- now = Time.now
+ now = Rainbows.now
fibs = []
ZZ.delete_if { |fib, time| now >= time ? fibs << fib : ! fib.alive? }
fibs.each { |fib| fib.resume if fib.alive? }
diff --git a/lib/rainbows/fiber/io.rb b/lib/rainbows/fiber/io.rb
index b121854..111132f 100644
--- a/lib/rainbows/fiber/io.rb
+++ b/lib/rainbows/fiber/io.rb
@@ -63,7 +63,7 @@ class Rainbows::Fiber::IO
expire = nil
case rv = Kgio.tryread(@to_io, 16384, buf)
when :wait_readable
- return if expire && expire < Time.now
+ return if expire && expire < Rainbows.now
expire ||= read_expire
kgio_wait_readable
else
diff --git a/lib/rainbows/join_threads.rb b/lib/rainbows/join_threads.rb
index 7ab2004..2ae6aa4 100644
--- a/lib/rainbows/join_threads.rb
+++ b/lib/rainbows/join_threads.rb
@@ -5,12 +5,12 @@ module Rainbows::JoinThreads
# blocking acceptor threads must be forced to run
def self.acceptors(threads)
- expire = Time.now + Rainbows.server.timeout
+ expire = Rainbows.now + Rainbows.server.timeout
threads.delete_if do |thr|
Rainbows.tick
begin
# blocking accept() may not wake up properly
- thr.raise(Errno::EINTR) if Time.now > expire && thr.stop?
+ thr.raise(Errno::EINTR) if Rainbows.now > expire && thr.stop?
thr.run
thr.join(0.01)
diff --git a/lib/rainbows/process_client.rb b/lib/rainbows/process_client.rb
index a39d6cd..4bf9878 100644
--- a/lib/rainbows/process_client.rb
+++ b/lib/rainbows/process_client.rb
@@ -9,7 +9,7 @@ module Rainbows::ProcessClient
Rainbows.config!(self, :client_header_buffer_size, :keepalive_timeout)
def read_expire
- Time.now + KEEPALIVE_TIMEOUT
+ Rainbows.now + KEEPALIVE_TIMEOUT
end
# used for reading headers (respecting keepalive_timeout)
@@ -18,7 +18,7 @@ module Rainbows::ProcessClient
begin
case rv = kgio_tryread(CLIENT_HEADER_BUFFER_SIZE, buf)
when :wait_readable
- return if expire && expire < Time.now
+ return if expire && expire < Rainbows.now
expire ||= read_expire
kgio_wait_readable(KEEPALIVE_TIMEOUT)
else
diff --git a/lib/rainbows/thread_timeout.rb b/lib/rainbows/thread_timeout.rb
index 8348272..8739d29 100644
--- a/lib/rainbows/thread_timeout.rb
+++ b/lib/rainbows/thread_timeout.rb
@@ -63,7 +63,7 @@ class Rainbows::ThreadTimeout
# The MRI 1.8 won't be usable in January 2038, we'll raise this
# when we eventually drop support for 1.8 (before 2038, hopefully)
- NEVER = Time.at(0x7fffffff)
+ NEVER = 0x7fffffff
def initialize(app, opts)
# @timeout must be Numeric since we add this to Time
@@ -114,7 +114,7 @@ class Rainbows::ThreadTimeout
# is hopeless and we might as well just die anyways.
# initialize guarantees @timeout will be Numeric
start_watchdog(env) unless @watchdog
- @active[Thread.current] = Time.now + @timeout
+ @active[Thread.current] = Rainbows.now + @timeout
begin
# It is important to unlock inside this begin block
@@ -162,7 +162,7 @@ class Rainbows::ThreadTimeout
# that are about to release themselves from the eye of the
# watchdog thread.
@lock.synchronize do
- now = Time.now
+ now = Rainbows.now
@active.delete_if do |thread, expire_at|
# We also use this loop to get the maximum possible time to
# sleep for if we're not killing the thread.
@@ -184,7 +184,7 @@ class Rainbows::ThreadTimeout
sleep(@timeout)
else
# sleep until the next known thread is about to expire.
- sec = next_expiry - Time.now
+ sec = next_expiry - Rainbows.now
sec > 0.0 ? sleep(sec) : Thread.pass # give other threads a chance
end
rescue => e
diff --git a/lib/rainbows/xepoll_thread_pool/client.rb b/lib/rainbows/xepoll_thread_pool/client.rb
index 001e69d..760bbde 100644
--- a/lib/rainbows/xepoll_thread_pool/client.rb
+++ b/lib/rainbows/xepoll_thread_pool/client.rb
@@ -46,7 +46,7 @@ module Rainbows::XEpollThreadPool::Client
LOCK.synchronize { clients = KATO.keys; KATO.clear }
clients.each { |io| io.closed? or io.close }
end
- @@last_expire = Time.now
+ @@last_expire = Rainbows.now
def kato_set
LOCK.synchronize { KATO[self] = @@last_expire }
@@ -70,7 +70,7 @@ module Rainbows::XEpollThreadPool::Client
end
def self.expire
- return if ((now = Time.now) - @@last_expire) < 1.0
+ return if ((now = Rainbows.now) - @@last_expire) < 1.0
if (ot = KEEPALIVE_TIMEOUT) >= 0
ot = now - ot
defer = []
diff --git a/lib/rainbows/xepoll_thread_spawn/client.rb b/lib/rainbows/xepoll_thread_spawn/client.rb
index a3277cf..67c5976 100644
--- a/lib/rainbows/xepoll_thread_spawn/client.rb
+++ b/lib/rainbows/xepoll_thread_spawn/client.rb
@@ -35,7 +35,7 @@ module Rainbows::XEpollThreadSpawn::Client
LOCK.synchronize { clients = KATO.keys; KATO.clear }
clients.each { |io| io.closed? or io.shutdown }
end
- @@last_expire = Time.now
+ @@last_expire = Rainbows.now
def kato_set
LOCK.synchronize { KATO[self] = @@last_expire }
@@ -59,7 +59,7 @@ module Rainbows::XEpollThreadSpawn::Client
end
def self.expire
- return if ((now = Time.now) - @@last_expire) < 1.0
+ return if ((now = Rainbows.now) - @@last_expire) < 1.0
if (ot = KEEPALIVE_TIMEOUT) >= 0
ot = now - ot
defer = []
diff --git a/rainbows.gemspec b/rainbows.gemspec
index afc8b5a..6ddf630 100644
--- a/rainbows.gemspec
+++ b/rainbows.gemspec
@@ -27,7 +27,7 @@ Gem::Specification.new do |s|
# we need unicorn for the HTTP parser and process management
# we need unicorn 4.8.0+ since we depend on undocumented/unsupported
# unicorn internals.
- s.add_dependency(%q<unicorn>, ["~> 4.8"])
+ s.add_dependency(%q<unicorn>, ["~> 5.0"])
s.add_development_dependency(%q<isolate>, "~> 3.1")
s.add_development_dependency(%q<olddoc>, "~> 1.0")
diff --git a/t/test_isolate.rb b/t/test_isolate.rb
index 98918f6..58bc4dc 100644
--- a/t/test_isolate.rb
+++ b/t/test_isolate.rb
@@ -20,7 +20,7 @@ Isolate.now!(opts) do
gem 'rack', '1.6.4'
gem 'kcar', '0.5.0'
gem 'raindrops', '0.13.0'
- gem 'unicorn', '4.9.0'
+ gem 'unicorn', '5.0.1'
if engine == "ruby"
gem 'sendfile', '1.2.2'
--
EW
^ permalink raw reply related [relevance 4%]
* [PATCH 0/3] final round of changes for unicorn 5 compatibility
@ 2015-11-18 3:58 7% Eric Wong
2015-11-18 3:58 4% ` [PATCH 3/3] bump to unicorn 5.0.1, use monotonic clock Eric Wong
0 siblings, 1 reply; 3+ results
From: Eric Wong @ 2015-11-18 3:58 UTC (permalink / raw)
To: rainbows-public
* http_server: add master_pid attribute
* stream_response_epoll: remove hijack_prepare call
* bump to unicorn 5.0.1, use monotonic clock
There'll probably be another round of small changes since we
can drop Ruby 1.8 support and debloat our code a little.
lib/rainbows.rb | 19 ++++++++++++++++---
lib/rainbows/coolio/client.rb | 2 +-
lib/rainbows/coolio/heartbeat.rb | 2 +-
lib/rainbows/epoll/client.rb | 4 ++--
lib/rainbows/fiber.rb | 2 +-
lib/rainbows/fiber/base.rb | 4 ++--
lib/rainbows/fiber/coolio/heartbeat.rb | 2 +-
lib/rainbows/fiber/io.rb | 2 +-
lib/rainbows/http_server.rb | 1 +
lib/rainbows/join_threads.rb | 4 ++--
lib/rainbows/process_client.rb | 4 ++--
lib/rainbows/stream_response_epoll.rb | 2 +-
lib/rainbows/thread_timeout.rb | 8 ++++----
lib/rainbows/xepoll_thread_pool/client.rb | 4 ++--
lib/rainbows/xepoll_thread_spawn/client.rb | 4 ++--
rainbows.gemspec | 2 +-
t/test_isolate.rb | 2 +-
17 files changed, 41 insertions(+), 27 deletions(-)
^ permalink raw reply [relevance 7%]
Results 1-3 of 3 | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
2015-11-18 3:58 7% [PATCH 0/3] final round of changes for unicorn 5 compatibility Eric Wong
2015-11-18 3:58 4% ` [PATCH 3/3] bump to unicorn 5.0.1, use monotonic clock Eric Wong
2015-11-25 1:04 6% [ANN] Rainbows! 5.0.0 - Rack HTTP server for the sleepy 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).