2015-10-01 19:37:58 -04:00
|
|
|
#!/usr/bin/env ruby
|
|
|
|
|
|
|
|
# Quiet some warnings we see when running in warning mode:
|
|
|
|
# RUBYOPT=-w bundle exec sidekiq
|
|
|
|
$TESTING = false
|
|
|
|
|
2015-10-07 17:27:47 -04:00
|
|
|
#require 'ruby-prof'
|
|
|
|
|
2015-10-01 19:37:58 -04:00
|
|
|
require_relative '../lib/sidekiq/cli'
|
|
|
|
require_relative '../lib/sidekiq/launcher'
|
|
|
|
|
|
|
|
include Sidekiq::Util
|
|
|
|
|
2015-10-07 19:56:10 -04:00
|
|
|
# brew tap shopify/shopify
|
|
|
|
# brew install toxiproxy
|
|
|
|
# gem install toxiproxy
|
|
|
|
require 'toxiproxy'
|
|
|
|
# simulate a non-localhost network for realer-world conditions.
|
|
|
|
# adding 1ms of network latency has an ENORMOUS impact on benchmarks
|
|
|
|
Toxiproxy.populate([{
|
|
|
|
"name": "redis",
|
|
|
|
"listen": "127.0.0.1:6380",
|
|
|
|
"upstream": "127.0.0.1:6379"
|
|
|
|
}])
|
|
|
|
|
|
|
|
|
2015-10-01 19:37:58 -04:00
|
|
|
Sidekiq.configure_server do |config|
|
2015-10-07 19:56:10 -04:00
|
|
|
config.redis = { db: 13, port: 6380 }
|
|
|
|
#config.redis = { db: 13 }
|
2015-10-01 19:37:58 -04:00
|
|
|
config.options[:queues] << 'default'
|
|
|
|
config.logger.level = Logger::ERROR
|
|
|
|
config.average_scheduled_poll_interval = 2
|
|
|
|
end
|
|
|
|
|
|
|
|
class LoadWorker
|
|
|
|
include Sidekiq::Worker
|
|
|
|
sidekiq_options retry: 1
|
|
|
|
sidekiq_retry_in do |x|
|
|
|
|
1
|
|
|
|
end
|
|
|
|
|
|
|
|
def perform(idx)
|
2015-10-07 19:56:10 -04:00
|
|
|
#raise idx.to_s if idx % 100 == 1
|
2015-10-01 19:37:58 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-10-07 22:20:17 -04:00
|
|
|
# brew tap shopify/shopify
|
|
|
|
# brew install toxiproxy
|
|
|
|
# gem install toxiproxy
|
|
|
|
require 'toxiproxy'
|
|
|
|
# simulate a non-localhost network for realer-world conditions.
|
|
|
|
# adding 1ms of network latency has an ENORMOUS impact on benchmarks
|
|
|
|
Toxiproxy.populate([{
|
|
|
|
"name": "redis",
|
|
|
|
"listen": "127.0.0.1:6380",
|
|
|
|
"upstream": "127.0.0.1:6379"
|
|
|
|
}])
|
|
|
|
|
2015-10-01 19:37:58 -04:00
|
|
|
self_read, self_write = IO.pipe
|
|
|
|
%w(INT TERM USR1 USR2 TTIN).each do |sig|
|
|
|
|
begin
|
|
|
|
trap sig do
|
|
|
|
self_write.puts(sig)
|
|
|
|
end
|
|
|
|
rescue ArgumentError
|
|
|
|
puts "Signal #{sig} not supported"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-10-07 22:20:17 -04:00
|
|
|
Sidekiq.redis {|c| c.flushdb}
|
2015-10-01 19:37:58 -04:00
|
|
|
def handle_signal(launcher, sig)
|
|
|
|
Sidekiq.logger.debug "Got #{sig} signal"
|
|
|
|
case sig
|
|
|
|
when 'INT'
|
|
|
|
# Handle Ctrl-C in JRuby like MRI
|
|
|
|
# http://jira.codehaus.org/browse/JRUBY-4637
|
|
|
|
raise Interrupt
|
|
|
|
when 'TERM'
|
|
|
|
# Heroku sends TERM and then waits 10 seconds for process to exit.
|
|
|
|
raise Interrupt
|
|
|
|
when 'USR1'
|
|
|
|
Sidekiq.logger.info "Received USR1, no longer accepting new work"
|
2015-10-06 17:51:06 -04:00
|
|
|
launcher.quiet
|
2015-10-01 19:37:58 -04:00
|
|
|
when 'USR2'
|
|
|
|
if Sidekiq.options[:logfile]
|
|
|
|
Sidekiq.logger.info "Received USR2, reopening log file"
|
|
|
|
Sidekiq::Logging.reopen_logs
|
|
|
|
end
|
|
|
|
when 'TTIN'
|
|
|
|
Thread.list.each do |thread|
|
|
|
|
Sidekiq.logger.warn "Thread TID-#{thread.object_id.to_s(36)} #{thread['label']}"
|
|
|
|
if thread.backtrace
|
|
|
|
Sidekiq.logger.warn thread.backtrace.join("\n")
|
|
|
|
else
|
|
|
|
Sidekiq.logger.warn "<no backtrace available>"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def Process.rss
|
|
|
|
`ps -o rss= -p #{Process.pid}`.chomp.to_i
|
|
|
|
end
|
|
|
|
|
|
|
|
iter = 10
|
|
|
|
count = 10_000
|
|
|
|
|
2015-10-07 17:27:47 -04:00
|
|
|
iter.times do
|
|
|
|
arr = Array.new(count) do
|
|
|
|
[]
|
|
|
|
end
|
|
|
|
count.times do |idx|
|
|
|
|
arr[idx][0] = idx
|
2015-10-01 19:37:58 -04:00
|
|
|
end
|
2015-10-07 17:27:47 -04:00
|
|
|
Sidekiq::Client.push_bulk('class' => LoadWorker, 'args' => arr)
|
2015-10-01 19:37:58 -04:00
|
|
|
end
|
2015-10-07 17:27:47 -04:00
|
|
|
Sidekiq.logger.error "Created #{count*iter} jobs"
|
2015-10-01 19:37:58 -04:00
|
|
|
|
|
|
|
Monitoring = Thread.new do
|
|
|
|
watchdog("monitor thread") do
|
|
|
|
while true
|
|
|
|
sleep 2
|
|
|
|
qsize, retries = Sidekiq.redis do |conn|
|
|
|
|
conn.pipelined do
|
|
|
|
conn.llen "queue:default"
|
|
|
|
conn.zcard "retry"
|
|
|
|
end
|
|
|
|
end.map(&:to_i)
|
|
|
|
total = qsize + retries
|
2015-10-07 17:27:47 -04:00
|
|
|
#GC.start
|
2015-10-01 19:37:58 -04:00
|
|
|
Sidekiq.logger.error("RSS: #{Process.rss} Pending: #{total}")
|
|
|
|
if total == 0
|
|
|
|
Sidekiq.logger.error("Done")
|
|
|
|
exit(0)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
begin
|
2015-10-07 17:27:47 -04:00
|
|
|
#RubyProf::exclude_threads = [ Monitoring ]
|
|
|
|
#RubyProf.start
|
2015-10-07 19:56:10 -04:00
|
|
|
Sidekiq.logger.error "Simulating 1ms of latency between Sidekiq and redis"
|
|
|
|
Toxiproxy[:redis].downstream(:latency, latency: 1).apply do
|
|
|
|
launcher = Sidekiq::Launcher.new(Sidekiq.options)
|
|
|
|
launcher.run
|
2015-10-01 19:37:58 -04:00
|
|
|
|
2015-10-07 19:56:10 -04:00
|
|
|
while readable_io = IO.select([self_read])
|
|
|
|
signal = readable_io.first[0].gets.strip
|
|
|
|
handle_signal(launcher, signal)
|
|
|
|
end
|
2015-10-01 19:37:58 -04:00
|
|
|
end
|
|
|
|
rescue SystemExit => e
|
2015-10-07 17:27:47 -04:00
|
|
|
#Sidekiq.logger.error("Profiling...")
|
|
|
|
#result = RubyProf.stop
|
|
|
|
#printer = RubyProf::GraphHtmlPrinter.new(result)
|
|
|
|
#printer.print(File.new("output.html", "w"), :min_percent => 1)
|
2015-10-01 19:37:58 -04:00
|
|
|
# normal
|
|
|
|
rescue => e
|
|
|
|
raise e if $DEBUG
|
|
|
|
STDERR.puts e.message
|
|
|
|
STDERR.puts e.backtrace.join("\n")
|
|
|
|
exit 1
|
|
|
|
end
|