unicorn Ruby/Rack server user+dev discussion/patches/pulls/bugs/help
 help / color / mirror / code / Atom feed
From: Eric Wong <e@80x24.org>
To: unicorn-public@bogomips.org
Subject: [PATCH] http_server: favor ivars over constants
Date: Thu, 12 Feb 2015 19:09:54 +0000	[thread overview]
Message-ID: <1423768194-29282-1-git-send-email-e@80x24.org> (raw)

In 1.9+ at least, instance variables use less space than constants
in class tables and bytecode, leading to ~700 byte reduction in
bytecode overhead on 64-bit and a reduction in constant table/entries
of the Unicorn::HttpServer class.
---
 lib/unicorn/http_server.rb | 77 +++++++++++++++++++++-------------------------
 1 file changed, 35 insertions(+), 42 deletions(-)

diff --git a/lib/unicorn/http_server.rb b/lib/unicorn/http_server.rb
index f0216d0..278b469 100644
--- a/lib/unicorn/http_server.rb
+++ b/lib/unicorn/http_server.rb
@@ -21,32 +21,12 @@ class Unicorn::HttpServer
   include Unicorn::SocketHelper
   include Unicorn::HttpResponse
 
-  # backwards compatibility with 1.x
-  Worker = Unicorn::Worker
-
   # all bound listener sockets
   LISTENERS = []
 
   # listeners we have yet to bind
   NEW_LISTENERS = []
 
-  # This hash maps PIDs to Workers
-  WORKERS = {}
-
-  # We use SELF_PIPE differently in the master and worker processes:
-  #
-  # * The master process never closes or reinitializes this once
-  # initialized.  Signal handlers in the master process will write to
-  # it to wake up the master from IO.select in exactly the same manner
-  # djb describes in http://cr.yp.to/docs/selfpipe.html
-  #
-  # * The workers immediately close the pipe they inherit.  See the
-  # Unicorn::Worker class for the pipe workers use.
-  SELF_PIPE = []
-
-  # signal queue used for self-piping
-  SIG_QUEUE = []
-
   # list of signals we care about and trap in master.
   QUEUE_SIGS = [ :WINCH, :QUIT, :INT, :TERM, :USR1, :USR2, :HUP, :TTIN, :TTOU ]
 
@@ -98,6 +78,19 @@ class Unicorn::HttpServer
     self.config = Unicorn::Configurator.new(options)
     self.listener_opts = {}
 
+    # We use @self_pipe differently in the master and worker processes:
+    #
+    # * The master process never closes or reinitializes this once
+    # initialized.  Signal handlers in the master process will write to
+    # it to wake up the master from IO.select in exactly the same manner
+    # djb describes in http://cr.yp.to/docs/selfpipe.html
+    #
+    # * The workers immediately close the pipe they inherit.  See the
+    # Unicorn::Worker class for the pipe workers use.
+    @self_pipe = []
+    @workers = {} # hash maps PIDs to Workers
+    @sig_queue = [] # signal queue used for self-piping
+
     # we try inheriting listeners first, so we bind them later.
     # we don't write the pid file until we've bound listeners in case
     # unicorn was started twice by mistake.  Even though our #pid= method
@@ -117,13 +110,13 @@ class Unicorn::HttpServer
     inherit_listeners!
     # this pipe is used to wake us up from select(2) in #join when signals
     # are trapped.  See trap_deferred.
-    SELF_PIPE.replace(Unicorn.pipe)
+    @self_pipe.replace(Unicorn.pipe)
     @master_pid = $$
 
     # setup signal handlers before writing pid file in case people get
     # trigger happy and send signals as soon as the pid file exists.
     # Note that signals don't actually get handled until the #join method
-    QUEUE_SIGS.each { |sig| trap(sig) { SIG_QUEUE << sig; awaken_master } }
+    QUEUE_SIGS.each { |sig| trap(sig) { @sig_queue << sig; awaken_master } }
     trap(:CHLD) { awaken_master }
 
     # write pid early for Mongrel compatibility if we're not inheriting sockets
@@ -276,7 +269,7 @@ class Unicorn::HttpServer
     end
     begin
       reap_all_workers
-      case SIG_QUEUE.shift
+      case @sig_queue.shift
       when nil
         # avoid murdering workers after our master process (or the
         # machine) comes out of suspend/hibernation
@@ -335,7 +328,7 @@ class Unicorn::HttpServer
   def stop(graceful = true)
     self.listeners = []
     limit = time_now + timeout
-    until WORKERS.empty? || time_now > limit
+    until @workers.empty? || time_now > limit
       if graceful
         soft_kill_each_worker(:QUIT)
       else
@@ -376,13 +369,13 @@ class Unicorn::HttpServer
 
   # wait for a signal hander to wake us up and then consume the pipe
   def master_sleep(sec)
-    IO.select([ SELF_PIPE[0] ], nil, nil, sec) or return
-    SELF_PIPE[0].kgio_tryread(11)
+    IO.select([ @self_pipe[0] ], nil, nil, sec) or return
+    @self_pipe[0].kgio_tryread(11)
   end
 
   def awaken_master
     return if $$ != @master_pid
-    SELF_PIPE[1].kgio_trywrite('.') # wakeup master process from select
+    @self_pipe[1].kgio_trywrite('.') # wakeup master process from select
   end
 
   # reaps all unreaped workers
@@ -396,7 +389,7 @@ class Unicorn::HttpServer
         self.pid = pid.chomp('.oldbin') if pid
         proc_name 'master'
       else
-        worker = WORKERS.delete(wpid) and worker.close rescue nil
+        worker = @workers.delete(wpid) and worker.close rescue nil
         m = "reaped #{status.inspect} worker=#{worker.nr rescue 'unknown'}"
         status.success? ? logger.info(m) : logger.error(m)
       end
@@ -465,7 +458,7 @@ class Unicorn::HttpServer
   def murder_lazy_workers
     next_sleep = @timeout - 1
     now = time_now.to_i
-    WORKERS.dup.each_pair do |wpid, worker|
+    @workers.dup.each_pair do |wpid, worker|
       tick = worker.tick
       0 == tick and next # skip workers that haven't processed any clients
       diff = now - tick
@@ -483,7 +476,7 @@ class Unicorn::HttpServer
   end
 
   def after_fork_internal
-    SELF_PIPE.each(&:close).clear # this is master-only, now
+    @self_pipe.each(&:close).clear # this is master-only, now
     @ready_pipe.close if @ready_pipe
     Unicorn::Configurator::RACKUP.clear
     @ready_pipe = @init_listeners = @before_exec = @before_fork = nil
@@ -498,11 +491,11 @@ class Unicorn::HttpServer
   def spawn_missing_workers
     worker_nr = -1
     until (worker_nr += 1) == @worker_processes
-      WORKERS.value?(worker_nr) and next
-      worker = Worker.new(worker_nr)
+      @workers.value?(worker_nr) and next
+      worker = Unicorn::Worker.new(worker_nr)
       before_fork.call(self, worker)
       if pid = fork
-        WORKERS[pid] = worker
+        @workers[pid] = worker
         worker.atfork_parent
       else
         after_fork_internal
@@ -516,9 +509,9 @@ class Unicorn::HttpServer
   end
 
   def maintain_worker_count
-    (off = WORKERS.size - worker_processes) == 0 and return
+    (off = @workers.size - worker_processes) == 0 and return
     off < 0 and return spawn_missing_workers
-    WORKERS.each_value { |w| w.nr >= worker_processes and w.soft_kill(:QUIT) }
+    @workers.each_value { |w| w.nr >= worker_processes and w.soft_kill(:QUIT) }
   end
 
   # if we get any error, try to write something back to the client
@@ -597,13 +590,13 @@ class Unicorn::HttpServer
     worker.atfork_child
     # we'll re-trap :QUIT later for graceful shutdown iff we accept clients
     EXIT_SIGS.each { |sig| trap(sig) { exit!(0) } }
-    exit!(0) if (SIG_QUEUE & EXIT_SIGS)[0]
+    exit!(0) if (@sig_queue & EXIT_SIGS)[0]
     WORKER_QUEUE_SIGS.each { |sig| trap(sig, nil) }
     trap(:CHLD, 'DEFAULT')
-    SIG_QUEUE.clear
+    @sig_queue.clear
     proc_name "worker[#{worker.nr}]"
     START_CTX.clear
-    WORKERS.clear
+    @workers.clear
 
     after_fork.call(self, worker) # can drop perms and create listeners
     LISTENERS.each { |sock| sock.close_on_exec = true }
@@ -683,17 +676,17 @@ class Unicorn::HttpServer
   # is no longer running.
   def kill_worker(signal, wpid)
     Process.kill(signal, wpid)
-    rescue Errno::ESRCH
-      worker = WORKERS.delete(wpid) and worker.close rescue nil
+  rescue Errno::ESRCH
+    worker = @workers.delete(wpid) and worker.close rescue nil
   end
 
   # delivers a signal to each worker
   def kill_each_worker(signal)
-    WORKERS.keys.each { |wpid| kill_worker(signal, wpid) }
+    @workers.keys.each { |wpid| kill_worker(signal, wpid) }
   end
 
   def soft_kill_each_worker(signal)
-    WORKERS.each_value { |worker| worker.soft_kill(signal) }
+    @workers.each_value { |worker| worker.soft_kill(signal) }
   end
 
   # unlinks a PID file at given +path+ if it contains the current PID
-- 
EW


                 reply	other threads:[~2015-02-12 19:09 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://yhbt.net/unicorn/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1423768194-29282-1-git-send-email-e@80x24.org \
    --to=e@80x24.org \
    --cc=unicorn-public@bogomips.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://yhbt.net/unicorn.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).