Module RubyRunCommander__
In: lib/rubyrun/rubyrun_commander__.rb

Methods

Public Instance methods

Show the top 20 Ruby classes which have the largest no. of instances in memory The snapshot is taken after a gc call is made

[Source]

     # File lib/rubyrun/rubyrun_commander__.rb, line 103
103:   def dump_object_map
104:     start_time = Time.now
105:     $rubyrun_obj_map_reporter = RubyRunHTMLWriter.new(@rubyrun_report_folder + '/' + File.basename($0, ".*") + '_' + $$.to_s + '_object_map.html', nil, shift_age = 10, shift_size = 4096000) unless $rubyrun_obj_map_reporter
106:     object_map = Hash.new
107:     ttl_object = 0
108:     ObjectSpace.garbage_collect
109:     ObjectSpace.each_object { |obj|
110:       ttl_object += 1
111:       object_map.has_key?(obj.class) ? object_map[obj.class] += 1 : object_map[obj.class] = 1        
112:     }
113:     results = object_map.sort{|a,b| a[1]<=>b[1]}.reverse!
114:     table_content = ''
115:     odd_row ||=true
116:     20.times {|i|
117:       table_content += sprintf("#{odd_row ? OBJ_MAP_ODD_ROW : OBJ_MAP_EVEN_ROW}",
118:                               results[i][0], results[i][1].to_s)
119:       odd_row = !odd_row
120:     }
121:     html_content = OBJ_MAP_HTML.sub(/%START_TIMESTAMP%/,start_time.strftime("%H:%M:%S %m/%d/%Y"))
122:     html_content.sub!(/%OBJ_MAP_ROW%/,table_content)
123:     $rubyrun_obj_map_reporter.info(html_content)
124:   end

Dump Controller/Actions response time metrics metrics structure metrics[0] Thread ID metrics[1] Timestamp of the request metrics[2] URL metrics[3] Controller name metrics[4] Action name metrics[5] Response time metrics[6] Action time metrics[7] Database IO time metrics[8] View time metrics[9] Uncaptured time metrics[10] Dispatch wait time

[Source]

    # File lib/rubyrun/rubyrun_commander__.rb, line 46
46:   def dump_reports(dump_all_reports = false)
47:     buffer = return_and_switch_buffer
48:     buffer.each { |metrics|
49:       # Last element is 1, representing a request count of 1, used for calculating average response time for this controller/action
50:       update_perf_metrics(metrics[3], {metrics[4] => [metrics[5],metrics[6],metrics[7],metrics[8],metrics[9],metrics[10],1]})
51:     }
52:     @rubyrun_req_count ||= 0
53:     @rubyrun_req_count += buffer.length
54:     if $rubyrun_config['OUTPUT'].include?(RUBYRUN_OUTPUT_PERF_SUMMARY) && dump_all_reports
55:       create_rss_channels if (!$rubyrun_perf_summary_rss && $rubyrun_rails_env)
56:       add_perf_summary_rss_item(@rubyrun_req_count)
57:       @rubyrun_req_count = 0
58:     end
59:     if $rubyrun_config['OUTPUT'].include?(RUBYRUN_OUTPUT_TXN_LOG)
60:       create_csv_files unless $rubyrun_txn_log_reporter
61:       add_txn_log_csv_item(buffer)
62:     end
63:     buffer.clear # Clear the buffer so that the main thread will push the data into a blank bucket
64:   end

Use Thread.list to list show thread status, and native code to display the last line # and function of the threads

[Source]

    # File lib/rubyrun/rubyrun_commander__.rb, line 20
20:   def dump_thread_status
21:     (unsupport_function; return) unless $rubyrun_native
22:     $rubyrun_thread_status_reporter = RubyRunHTMLWriter.new(@rubyrun_report_folder + '/' + File.basename($0, ".*") + '_' + $$.to_s + '_thread_status.html', nil, shift_age = 10, shift_size = 4096000) unless $rubyrun_thread_status_reporter
23:     start_time = Time.now
24:     th_data_hash = RubyRunNative__.get_all_top_stacks
25:     odd_row ||= true
26:     table_content = ''
27:     Thread.list.each {|th|
28:       thread_id = get_thread_id(th)
29:       table_content += sprintf("#{odd_row ? THREAD_STATUS_ODD_ROW : THREAD_STATUS_EVEN_ROW}",
30:                               thread_id, th.status, get_top_stack(th_data_hash, thread_id))
31:       odd_row = !odd_row
32:     }
33:     html_content = THREAD_STATUS_HTML.sub(/%START_TIMESTAMP%/,start_time.strftime("%H:%M:%S %m/%d/%Y"))
34:     html_content.sub!(/%THREAD_STATUS_ROW%/,table_content)
35:     $rubyrun_thread_status_reporter.info(html_content)
36:   end

If exists, indicate to the monitor thread to exit

[Source]

     # File lib/rubyrun/rubyrun_commander__.rb, line 187
187:   def exit_monitor?
188:     File.exists?(ENV[RUBYRUN_WORKING_DIR] + RUBYRUN_CMD_EXIT)   
189:   end

If exists, indicate to the monitor thread that a hard kill (kill all threads including the main thread) command is sent

[Source]

     # File lib/rubyrun/rubyrun_commander__.rb, line 177
177:   def hard_kill?
178:     File.exists?(ENV[RUBYRUN_WORKING_DIR] + RUBYRUN_CMD_HARD_KILL + '_' + Process.pid.to_s)   
179:   end

The way to do soft/hard kill is to performa a thr.raise on the thread from the thread monitor. Using the begin/rescue created around the block in Thread.new by RubyRunInstrumentor__, the raise will be rescued and $@ is then extracted to a global hash. Softkill only kills non-main threads. Hardkill kills the main thread also but as the last step.

[Source]

    # File lib/rubyrun/rubyrun_commander__.rb, line 72
72:   def kill_threads(monitor_thr)
73:     (unsupport_function; return) unless $rubyrun_native
74:     if !$rubyrun_thread_dump_reporter
75:       $rubyrun_thread_dump_reporter = Logger.new(@rubyrun_report_folder + '/' + File.basename($0, ".*") + '_' + $$.to_s + '_thread_dump.txt', shift_age = 10, shift_size = 4096000)
76:       $rubyrun_thread_dump_reporter.level = Logger::INFO
77:       class << $rubyrun_thread_dump_reporter
78:         include RubyRunUtils__
79:         def format_message (severity, timestamp, progname, msg)
80:           "[#{timestamp.strftime("%Y-%m-%d %H:%M:%S")}.#{("%.3f" % timestamp.to_f).split('.')[1]}] #{get_thread_id} #{msg}\n"
81:         end
82:       end
83:     end
84:     th_data_hash = RubyRunNative__.get_all_top_stacks 
85:     j_th_id = return_joined_thread(th_data_hash)
86:     Thread.list.each {|th|
87:       th_id = get_thread_id(th)
88:       if th.status == 'sleep' && th_id != get_thread_id && th_id != get_thread_id(monitor_thr) &&
89:         th_id != get_thread_id(Thread.main) && th_id != j_th_id
90:         $rubyrun_thread_dump_reporter.info "*** Raising exception #{RUBYRUN_KILL_3_STRING} to #{get_thread_id(th)} ***"
91:         th.raise ThreadError, RUBYRUN_KILL_3_STRING
92:       end
93:     }
94:     sleep 3
95:     back_trace_all(th_data_hash)
96:     hard_kill = hard_kill?
97:     remove_cmd_folder     
98:     Thread.main.raise ThreadError, RUBYRUN_KILL_3_STRING if hard_kill    
99:   end

If exists, indicate to the montior thread that a object map is requested

[Source]

     # File lib/rubyrun/rubyrun_commander__.rb, line 182
182:   def object_map?
183:     File.exists?(ENV[RUBYRUN_WORKING_DIR] + RUBYRUN_CMD_OBJECT_MAP)   
184:   end

Remove the cmd_kill-3 folder or file if any

[Source]

     # File lib/rubyrun/rubyrun_commander__.rb, line 155
155:   def remove_cmd_folder
156:     [RUBYRUN_CMD_SOFT_KILL, RUBYRUN_CMD_HARD_KILL].each { |cmd|
157:       path = ENV[RUBYRUN_WORKING_DIR] + cmd + '_' + Process.pid.to_s
158:       next unless File.exist?(path)
159:       File.directory?(path) ? Dir.delete(path) : File.delete(path)          
160:     }
161:   end

If a thread is joined this method returns the joining thread ID

[Source]

     # File lib/rubyrun/rubyrun_commander__.rb, line 145
145:   def return_joined_thread(th_data_hash)
146:     th_data_hash.each {|th, top_stack|
147:       if th.to_s.include?(get_thread_id(Thread.main))
148:         top_stack[0] =~ /\*\*(.+?)\*\*/
149:         return $1
150:       end
151:     }
152:   end

If exists, indicate to the monitor thread that a soft kill (kill all threads except the main thread) command is sent

[Source]

     # File lib/rubyrun/rubyrun_commander__.rb, line 171
171:   def soft_kill?
172:     File.exists?(ENV[RUBYRUN_WORKING_DIR] + RUBYRUN_CMD_SOFT_KILL + '_' + Process.pid.to_s)   
173:   end

If exists, indicate to the monitor thread that a thread status report is requested

[Source]

     # File lib/rubyrun/rubyrun_commander__.rb, line 165
165:   def thread_status?
166:     File.exists?(ENV[RUBYRUN_WORKING_DIR] + RUBYRUN_CMD_STATUS)   
167:   end

Log if native library can‘t be loaded or not found

[Source]

     # File lib/rubyrun/rubyrun_commander__.rb, line 192
192:   def unsupport_function
193:     $rubyrun_logger.info "Native library not available. Function not supported."
194:   end

metrics hash is a global collection point for all metrics (averaged) for all actions by controller Use serialization before updating this global hash Structure of $rubyrun_metrics_hash: controller_name => {action_name => [response_time, action_time,

                                    db_io_time, view_time,
                                    uncaptured_time, dispatch_wait_time,
                                    request_count]}

[Source]

     # File lib/rubyrun/rubyrun_commander__.rb, line 134
134:   def update_perf_metrics(controller, action_metrics_hash)
135:     $rubyrun_metrics_hash[controller].merge!(action_metrics_hash) {|action, o_metrics, new_metrics|
136:       o_metrics.each_index { |x|
137:         (o_metrics[x] += new_metrics[x]; break) if x == (o_metrics.length-1) # Calculate the total request count for this controller/action
138:         o_metrics[x] = (o_metrics[x] * o_metrics.last + new_metrics[x])/(o_metrics.last + new_metrics.last).to_f
139:       }
140:       o_metrics
141:     }
142:   end

[Validate]