Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@kares
Created December 22, 2014 15:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kares/0e68e079dd25fd21e054 to your computer and use it in GitHub Desktop.
Save kares/0e68e079dd25fd21e054 to your computer and use it in GitHub Desktop.
Celluloid.stack_dump tunings on JRuby
require 'celluloid/stack_dump'
module Celluloid
class StackDump
class ActorState
attr_accessor :thread_name, :thread_id
def dump
string = ""
string << "Celluloid::Actor 0x#{subject_id.to_s(16)}: #{subject_class}"
string << " [#{name}]" if name
if thread_id
string << " (##{thread_id}"
string << " #{thread_name}" if thread_name
string << ")"
end
string << "\n"
if status == :idle
string << "State: Idle (waiting for messages)\n"
display_backtrace backtrace, string
else
string << "State: Running (executing tasks)\n"
display_backtrace backtrace, string
string << "\tTasks:\n"
tasks.each_with_index do |task, i|
string << "\t #{i+1}) #{task.task_class}[#{task.type}]: #{task.status}\n"
string << "\t #{task.meta.inspect}\n"
display_backtrace task.backtrace, string, "\t"
end
end
string
end
end
class ThreadState
attr_accessor :thread_name
def dump
string = ""
if thread_name
string << "Thread (##{thread_id} #{thread_name}):\n"
else
string << "Thread 0x#{thread_id.to_s(16)}:\n"
end
display_backtrace backtrace, string
string
end
end
# attr_accessor :actors, :threads
#
# def initialize
# @actors = []
# @threads = []
#
# snapshot
# end
#
# def snapshot
# Celluloid.internal_pool.each do |thread|
# if thread.role == :actor
# @actors << snapshot_actor(thread.actor) if thread.actor
# else
# @threads << snapshot_thread(thread)
# end
# end
# end
def snapshot_actor(actor)
state = ActorState.new
state.subject_id = actor.subject.object_id
state.subject_class = actor.subject.class
tasks = actor.tasks
if tasks.empty?
state.status = :idle
else
state.status = :running
state.tasks = tasks.to_a.map { |t| TaskState.new(t.class, t.type, t.meta, t.status, t.backtrace) }
end
state.backtrace = actor.thread.backtrace if actor.thread
state.thread_id = real_thread_id(actor.thread) if actor.thread
state.thread_name = real_thread_name(actor.thread) if actor.thread
state
end
def snapshot_thread(thread)
state = ThreadState.new(thread.object_id, thread.backtrace)
id = real_thread_id(thread)
state.thread_id = id if id
name = real_thread_name(thread)
state.thread_name = name if name
state
end
def real_thread_name(thread)
if thread.is_a?(ThreadHandle)
if thread = thread.instance_variable_get(:@thread)
return thread[:name] || thread.to_java.native_thread.name
end
elsif thread.is_a?(::Thread)
return thread[:name] || thread.to_java.native_thread.name
end
nil
end
def real_thread_id(thread)
if thread.is_a?(ThreadHandle)
if thread = thread.instance_variable_get(:@thread)
return thread.object_id
end
elsif thread.is_a?(::Thread)
return thread.object_id
end
nil
end
def dump(output = STDERR)
@actors.each do |actor|
output.print actor.dump
end
@threads.each do |thread|
output.print thread.dump
end
end
end
end
## ROLL THIS SHIT :
Thread.new do
Thread.current[:name] = 'Celluloid.stack_dump'
Thread.current.to_java.native_thread.setPriority 5 + 2
every = 1.0; counter = 0
base = Time.now.strftime("%y-%m-%d@%H:%M:%S")
loop do
begin
sleep every
suffix = format '%04d', (counter += 1)
suffix << '_' << Time.now.strftime("%H:%M:%S")
file = "#{Rails.root}/log/celluloid_dump_#{base}.#{suffix}"
File.open(file, 'w') { |io| Celluloid.stack_dump(io) }
rescue => e
Logging.logger.root.error("Celluloid.stack_dump FAILED: #{e}\n #{e.backtrace.join("\n ")}")
end
end
end if false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment