ruby-prof 0.8.1-x86-mswin32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +221 -0
- data/LICENSE +23 -0
- data/README +432 -0
- data/Rakefile +159 -0
- data/bin/ruby-prof +224 -0
- data/examples/flat.txt +55 -0
- data/examples/graph.html +823 -0
- data/examples/graph.txt +170 -0
- data/ext/ruby_prof/measure_allocations.h +58 -0
- data/ext/ruby_prof/measure_cpu_time.h +152 -0
- data/ext/ruby_prof/measure_gc_runs.h +76 -0
- data/ext/ruby_prof/measure_gc_time.h +57 -0
- data/ext/ruby_prof/measure_memory.h +101 -0
- data/ext/ruby_prof/measure_process_time.h +52 -0
- data/ext/ruby_prof/measure_wall_time.h +53 -0
- data/ext/ruby_prof/mingw/Rakefile +23 -0
- data/ext/ruby_prof/mingw/build.rake +38 -0
- data/ext/ruby_prof/ruby_prof.c +1747 -0
- data/ext/ruby_prof/ruby_prof.h +188 -0
- data/ext/ruby_prof/version.h +4 -0
- data/lib/1.8/ruby_prof.so +0 -0
- data/lib/1.9/ruby_prof.so +0 -0
- data/lib/ruby-prof.rb +56 -0
- data/lib/ruby-prof/abstract_printer.rb +41 -0
- data/lib/ruby-prof/aggregate_call_info.rb +62 -0
- data/lib/ruby-prof/call_info.rb +47 -0
- data/lib/ruby-prof/call_tree_printer.rb +84 -0
- data/lib/ruby-prof/flat_printer.rb +78 -0
- data/lib/ruby-prof/flat_printer_with_line_numbers.rb +72 -0
- data/lib/ruby-prof/graph_html_printer.rb +256 -0
- data/lib/ruby-prof/graph_printer.rb +157 -0
- data/lib/ruby-prof/method_info.rb +111 -0
- data/lib/ruby-prof/symbol_to_proc.rb +8 -0
- data/lib/ruby-prof/task.rb +146 -0
- data/lib/ruby-prof/test.rb +148 -0
- data/lib/unprof.rb +8 -0
- data/rails/environment/profile.rb +24 -0
- data/rails/example/example_test.rb +9 -0
- data/rails/profile_test_helper.rb +21 -0
- data/test/aggregate_test.rb +121 -0
- data/test/basic_test.rb +290 -0
- data/test/current_failures_windows +8 -0
- data/test/do_nothing.rb +0 -0
- data/test/duplicate_names_test.rb +32 -0
- data/test/enumerable_test.rb +16 -0
- data/test/exceptions_test.rb +15 -0
- data/test/exclude_threads_test.rb +54 -0
- data/test/exec_test.rb +14 -0
- data/test/line_number_test.rb +73 -0
- data/test/measurement_test.rb +121 -0
- data/test/module_test.rb +54 -0
- data/test/no_method_class_test.rb +13 -0
- data/test/prime.rb +58 -0
- data/test/prime_test.rb +13 -0
- data/test/printers_test.rb +130 -0
- data/test/recursive_test.rb +275 -0
- data/test/ruby-prof-bin +20 -0
- data/test/singleton_test.rb +37 -0
- data/test/stack_test.rb +138 -0
- data/test/start_stop_test.rb +95 -0
- data/test/test_suite.rb +23 -0
- data/test/thread_test.rb +173 -0
- data/test/unique_call_path_test.rb +225 -0
- metadata +143 -0
@@ -0,0 +1,188 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (C) 2008 Shugo Maeda <shugo@ruby-lang.org>
|
3
|
+
* Charlie Savage <cfis@savagexi.com>
|
4
|
+
* All rights reserved.
|
5
|
+
*
|
6
|
+
* Redistribution and use in source and binary forms, with or without
|
7
|
+
* modification, are permitted provided that the following conditions
|
8
|
+
* are met:
|
9
|
+
* 1. Redistributions of source code must retain the above copyright
|
10
|
+
* notice, this list of conditions and the following disclaimer.
|
11
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
12
|
+
* notice, this list of conditions and the following disclaimer in the
|
13
|
+
* documentation and/or other materials provided with the distribution.
|
14
|
+
*
|
15
|
+
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
16
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
17
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
18
|
+
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
19
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
20
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
21
|
+
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
22
|
+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
23
|
+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
24
|
+
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
25
|
+
* SUCH DAMAGE.
|
26
|
+
*/
|
27
|
+
|
28
|
+
/* ruby-prof tracks the time spent executing every method in ruby programming.
|
29
|
+
The main players are:
|
30
|
+
|
31
|
+
prof_result_t - Its one field, values, contains the overall results
|
32
|
+
thread_data_t - Stores data about a single thread.
|
33
|
+
prof_stack_t - The method call stack in a particular thread
|
34
|
+
prof_method_t - Profiling information for each method
|
35
|
+
prof_call_info_t - Keeps track a method's callers and callees.
|
36
|
+
|
37
|
+
The final resulut is a hash table of thread_data_t, keyed on the thread
|
38
|
+
id. Each thread has an hash a table of prof_method_t, keyed on the
|
39
|
+
method id. A hash table is used for quick look up when doing a profile.
|
40
|
+
However, it is exposed to Ruby as an array.
|
41
|
+
|
42
|
+
Each prof_method_t has two hash tables, parent and children, of prof_call_info_t.
|
43
|
+
These objects keep track of a method's callers (who called the method) and its
|
44
|
+
callees (who the method called). These are keyed the method id, but once again,
|
45
|
+
are exposed to Ruby as arrays. Each prof_call_into_t maintains a pointer to the
|
46
|
+
caller or callee method, thereby making it easy to navigate through the call
|
47
|
+
hierarchy in ruby - which is very helpful for creating call graphs.
|
48
|
+
*/
|
49
|
+
|
50
|
+
/* #define DEBUG */
|
51
|
+
|
52
|
+
#ifndef RUBY_PROF_H
|
53
|
+
#define RUBY_PROF_H
|
54
|
+
|
55
|
+
#include <stdio.h>
|
56
|
+
|
57
|
+
#include <ruby.h>
|
58
|
+
|
59
|
+
#ifndef RUBY_VM
|
60
|
+
#include <node.h>
|
61
|
+
#include <st.h>
|
62
|
+
typedef rb_event_t rb_event_flag_t;
|
63
|
+
#define rb_sourcefile() (node ? node->nd_file : 0)
|
64
|
+
#define rb_sourceline() (node ? nd_line(node) : 0)
|
65
|
+
#endif
|
66
|
+
|
67
|
+
#include "version.h"
|
68
|
+
|
69
|
+
/* ================ Constants =================*/
|
70
|
+
#define INITIAL_STACK_SIZE 8
|
71
|
+
#define INITIAL_CALL_INFOS_SIZE 2
|
72
|
+
|
73
|
+
|
74
|
+
/* ================ Measurement =================*/
|
75
|
+
#ifdef HAVE_LONG_LONG
|
76
|
+
typedef unsigned LONG_LONG prof_measure_t; // long long is 8 bytes on 32-bit
|
77
|
+
#else
|
78
|
+
typedef unsigned long prof_measure_t;
|
79
|
+
#endif
|
80
|
+
|
81
|
+
#include "measure_process_time.h"
|
82
|
+
#include "measure_wall_time.h"
|
83
|
+
#include "measure_cpu_time.h"
|
84
|
+
#include "measure_allocations.h"
|
85
|
+
#include "measure_memory.h"
|
86
|
+
#include "measure_gc_runs.h"
|
87
|
+
#include "measure_gc_time.h"
|
88
|
+
|
89
|
+
static prof_measure_t (*get_measurement)() = measure_process_time;
|
90
|
+
static double (*convert_measurement)(prof_measure_t) = convert_process_time;
|
91
|
+
|
92
|
+
/* ================ DataTypes =================*/
|
93
|
+
static VALUE mProf;
|
94
|
+
static VALUE cResult;
|
95
|
+
static VALUE cMethodInfo;
|
96
|
+
static VALUE cCallInfo;
|
97
|
+
|
98
|
+
/* Profiling information for each method. */
|
99
|
+
typedef struct {
|
100
|
+
VALUE klass; /* The method's class. */
|
101
|
+
ID mid; /* The method id. */
|
102
|
+
int depth; /* The recursion depth. */
|
103
|
+
int key; /* Cache calculated key */
|
104
|
+
} prof_method_key_t;
|
105
|
+
|
106
|
+
struct prof_call_infos_t;
|
107
|
+
|
108
|
+
/* Profiling information for each method. */
|
109
|
+
typedef struct {
|
110
|
+
prof_method_key_t *key; /* Method key */
|
111
|
+
const char *source_file; /* The method's source file */
|
112
|
+
int line; /* The method's line number. */
|
113
|
+
int active; /* Is this recursion depth. */
|
114
|
+
struct prof_call_infos_t *call_infos; /* Call info objects for this method */
|
115
|
+
VALUE object; /* Cahced ruby object */
|
116
|
+
} prof_method_t;
|
117
|
+
|
118
|
+
/* Callers and callee information for a method. */
|
119
|
+
typedef struct prof_call_info_t {
|
120
|
+
prof_method_t *target; /* Use target instead of method to avoid conflict with Ruby method */
|
121
|
+
struct prof_call_info_t *parent;
|
122
|
+
st_table *call_infos;
|
123
|
+
int called;
|
124
|
+
prof_measure_t total_time;
|
125
|
+
prof_measure_t self_time;
|
126
|
+
prof_measure_t wait_time;
|
127
|
+
int line;
|
128
|
+
VALUE object;
|
129
|
+
VALUE children;
|
130
|
+
} prof_call_info_t;
|
131
|
+
|
132
|
+
/* Array of call_info objects */
|
133
|
+
typedef struct prof_call_infos_t {
|
134
|
+
prof_call_info_t **start;
|
135
|
+
prof_call_info_t **end;
|
136
|
+
prof_call_info_t **ptr;
|
137
|
+
VALUE object;
|
138
|
+
} prof_call_infos_t;
|
139
|
+
|
140
|
+
|
141
|
+
/* Temporary object that maintains profiling information
|
142
|
+
for active methods - there is one per method.*/
|
143
|
+
typedef struct {
|
144
|
+
/* Caching prof_method_t values significantly
|
145
|
+
increases performance. */
|
146
|
+
prof_call_info_t *call_info;
|
147
|
+
prof_measure_t start_time;
|
148
|
+
prof_measure_t wait_time;
|
149
|
+
prof_measure_t child_time;
|
150
|
+
unsigned int line;
|
151
|
+
} prof_frame_t;
|
152
|
+
|
153
|
+
/* Current stack of active methods.*/
|
154
|
+
typedef struct {
|
155
|
+
prof_frame_t *start;
|
156
|
+
prof_frame_t *end;
|
157
|
+
prof_frame_t *ptr;
|
158
|
+
} prof_stack_t;
|
159
|
+
|
160
|
+
/* Profiling information for a thread. */
|
161
|
+
typedef struct {
|
162
|
+
VALUE thread_id; /* Thread id */
|
163
|
+
st_table* method_table; /* Methods called in the thread */
|
164
|
+
prof_stack_t* stack; /* Active methods */
|
165
|
+
prof_measure_t last_switch; /* Point of last context switch */
|
166
|
+
} thread_data_t;
|
167
|
+
|
168
|
+
typedef struct {
|
169
|
+
VALUE threads;
|
170
|
+
} prof_result_t;
|
171
|
+
|
172
|
+
|
173
|
+
/* ================ Variables =================*/
|
174
|
+
static int measure_mode;
|
175
|
+
static st_table *threads_tbl = NULL;
|
176
|
+
static st_table *exclude_threads_tbl = NULL;
|
177
|
+
|
178
|
+
/* TODO - If Ruby become multi-threaded this has to turn into
|
179
|
+
a separate stack since this isn't thread safe! */
|
180
|
+
static thread_data_t* last_thread_data = NULL;
|
181
|
+
|
182
|
+
|
183
|
+
/* Forward declarations */
|
184
|
+
static VALUE prof_call_infos_wrap(prof_call_infos_t *call_infos);
|
185
|
+
static VALUE prof_call_info_wrap(prof_call_info_t *call_info);
|
186
|
+
static VALUE prof_method_wrap(prof_method_t *result);
|
187
|
+
|
188
|
+
#endif
|
Binary file
|
Binary file
|
data/lib/ruby-prof.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# require the .so file
|
2
|
+
me = File.dirname(__FILE__) + '/'
|
3
|
+
begin
|
4
|
+
# fat binaries
|
5
|
+
require "#{me}/#{RUBY_VERSION[0..2]}/ruby_prof"
|
6
|
+
rescue Exception
|
7
|
+
require "#{me}/../ext/ruby_prof/ruby_prof"
|
8
|
+
end
|
9
|
+
|
10
|
+
require "ruby-prof/method_info"
|
11
|
+
require "ruby-prof/call_info"
|
12
|
+
require "ruby-prof/aggregate_call_info"
|
13
|
+
require "ruby-prof/flat_printer"
|
14
|
+
require "ruby-prof/flat_printer_with_line_numbers"
|
15
|
+
require "ruby-prof/graph_printer"
|
16
|
+
require "ruby-prof/graph_html_printer"
|
17
|
+
require "ruby-prof/call_tree_printer"
|
18
|
+
require "ruby-prof/symbol_to_proc" # for 1.8's benefit
|
19
|
+
#require "ruby-prof/result"
|
20
|
+
|
21
|
+
module RubyProf
|
22
|
+
# See if the user specified the clock mode via
|
23
|
+
# the RUBY_PROF_MEASURE_MODE environment variable
|
24
|
+
def self.figure_measure_mode
|
25
|
+
case ENV["RUBY_PROF_MEASURE_MODE"]
|
26
|
+
when "wall" || "wall_time"
|
27
|
+
RubyProf.measure_mode = RubyProf::WALL_TIME
|
28
|
+
when "cpu" || "cpu_time"
|
29
|
+
if ENV.key?("RUBY_PROF_CPU_FREQUENCY")
|
30
|
+
RubyProf.cpu_frequency = ENV["RUBY_PROF_CPU_FREQUENCY"].to_f
|
31
|
+
else
|
32
|
+
begin
|
33
|
+
open("/proc/cpuinfo") do |f|
|
34
|
+
f.each_line do |line|
|
35
|
+
s = line.slice(/cpu MHz\s*:\s*(.*)/, 1)
|
36
|
+
if s
|
37
|
+
RubyProf.cpu_frequency = s.to_f * 1000000
|
38
|
+
break
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
rescue Errno::ENOENT
|
43
|
+
end
|
44
|
+
end
|
45
|
+
RubyProf.measure_mode = RubyProf::CPU_TIME
|
46
|
+
when "allocations"
|
47
|
+
RubyProf.measure_mode = RubyProf::ALLOCATIONS
|
48
|
+
when "memory"
|
49
|
+
RubyProf.measure_mode = RubyProf::MEMORY
|
50
|
+
else
|
51
|
+
RubyProf.measure_mode = RubyProf::PROCESS_TIME
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
RubyProf::figure_measure_mode
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module RubyProf
|
2
|
+
class AbstractPrinter
|
3
|
+
def initialize(result)
|
4
|
+
@result = result
|
5
|
+
@output = nil
|
6
|
+
@options = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
# Specify print options.
|
10
|
+
#
|
11
|
+
# options - Hash table
|
12
|
+
# :min_percent - Number 0 to 100 that specifes the minimum
|
13
|
+
# %self (the methods self time divided by the
|
14
|
+
# overall total time) that a method must take
|
15
|
+
# for it to be printed out in the report.
|
16
|
+
# Default value is 0.
|
17
|
+
#
|
18
|
+
# :print_file - True or false. Specifies if a method's source
|
19
|
+
# file should be printed. Default value if false.
|
20
|
+
#
|
21
|
+
def setup_options(options = {})
|
22
|
+
@options = options
|
23
|
+
end
|
24
|
+
|
25
|
+
def min_percent
|
26
|
+
@options[:min_percent] || 0
|
27
|
+
end
|
28
|
+
|
29
|
+
def print_file
|
30
|
+
@options[:print_file] || false
|
31
|
+
end
|
32
|
+
|
33
|
+
def method_name(method)
|
34
|
+
name = method.full_name
|
35
|
+
if print_file
|
36
|
+
name += " (#{method.source_file}:#{method.line}}"
|
37
|
+
end
|
38
|
+
name
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module RubyProf
|
2
|
+
class AggregateCallInfo
|
3
|
+
attr_reader :call_infos
|
4
|
+
def initialize(call_infos)
|
5
|
+
if call_infos.length == 0
|
6
|
+
raise(ArgumentError, "Must specify at least one call info.")
|
7
|
+
end
|
8
|
+
@call_infos = call_infos
|
9
|
+
end
|
10
|
+
|
11
|
+
def target
|
12
|
+
call_infos.first.target
|
13
|
+
end
|
14
|
+
|
15
|
+
def parent
|
16
|
+
call_infos.first.parent
|
17
|
+
end
|
18
|
+
|
19
|
+
def line
|
20
|
+
call_infos.first.line
|
21
|
+
end
|
22
|
+
|
23
|
+
def children
|
24
|
+
call_infos.inject(Array.new) do |result, call_info|
|
25
|
+
result.concat(call_info.children)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def total_time
|
30
|
+
aggregate(:total_time)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self_time
|
34
|
+
aggregate(:self_time)
|
35
|
+
end
|
36
|
+
|
37
|
+
def wait_time
|
38
|
+
aggregate(:wait_time)
|
39
|
+
end
|
40
|
+
|
41
|
+
def children_time
|
42
|
+
aggregate(:children_time)
|
43
|
+
end
|
44
|
+
|
45
|
+
def called
|
46
|
+
aggregate(:called)
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_s
|
50
|
+
"#{call_infos.first.full_name}"
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def aggregate(method_name)
|
56
|
+
self.call_infos.inject(0) do |sum, call_info|
|
57
|
+
sum += call_info.send(method_name)
|
58
|
+
sum
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module RubyProf
|
2
|
+
class CallInfo
|
3
|
+
def depth
|
4
|
+
result = 0
|
5
|
+
call_info = self.parent
|
6
|
+
|
7
|
+
while call_info
|
8
|
+
result += 1
|
9
|
+
call_info = call_info.parent
|
10
|
+
end
|
11
|
+
result
|
12
|
+
end
|
13
|
+
|
14
|
+
def children_time
|
15
|
+
children.inject(0) do |sum, call_info|
|
16
|
+
sum += call_info.total_time
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def stack
|
21
|
+
@stack ||= begin
|
22
|
+
methods = Array.new
|
23
|
+
call_info = self
|
24
|
+
|
25
|
+
while call_info
|
26
|
+
methods << call_info.target
|
27
|
+
call_info = call_info.parent
|
28
|
+
end
|
29
|
+
methods.reverse
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def call_sequence
|
34
|
+
@call_sequence ||= begin
|
35
|
+
stack.map {|method| method.full_name}.join('->')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def root?
|
40
|
+
self.parent.nil?
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_s
|
44
|
+
"#{call_sequence}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'ruby-prof/abstract_printer'
|
2
|
+
|
3
|
+
module RubyProf
|
4
|
+
# Generate profiling information in calltree format
|
5
|
+
# for use by kcachegrind and similar tools.
|
6
|
+
|
7
|
+
class CallTreePrinter < AbstractPrinter
|
8
|
+
def print(output = STDOUT, options = {})
|
9
|
+
@output = output
|
10
|
+
setup_options(options)
|
11
|
+
|
12
|
+
# add a header - this information is somewhat arbitrary
|
13
|
+
@output << "events: "
|
14
|
+
case RubyProf.measure_mode
|
15
|
+
when RubyProf::PROCESS_TIME
|
16
|
+
@value_scale = RubyProf::CLOCKS_PER_SEC;
|
17
|
+
@output << 'process_time'
|
18
|
+
when RubyProf::WALL_TIME
|
19
|
+
@value_scale = 1_000_000
|
20
|
+
@output << 'wall_time'
|
21
|
+
when RubyProf.const_defined?(:CPU_TIME) && RubyProf::CPU_TIME
|
22
|
+
@value_scale = RubyProf.cpu_frequency
|
23
|
+
@output << 'cpu_time'
|
24
|
+
when RubyProf.const_defined?(:ALLOCATIONS) && RubyProf::ALLOCATIONS
|
25
|
+
@value_scale = 1
|
26
|
+
@output << 'allocations'
|
27
|
+
when RubyProf.const_defined?(:MEMORY) && RubyProf::MEMORY
|
28
|
+
@value_scale = 1
|
29
|
+
@output << 'memory'
|
30
|
+
when RubyProf.const_defined?(:GC_RUNS) && RubyProf::GC_RUNS
|
31
|
+
@value_scale = 1
|
32
|
+
@output << 'gc_runs'
|
33
|
+
when RubyProf.const_defined?(:GC_TIME) && RubyProf::GC_TIME
|
34
|
+
@value_scale = 1000000
|
35
|
+
@output << 'gc_time'
|
36
|
+
else
|
37
|
+
raise "Unknown measure mode: #{RubyProf.measure_mode}"
|
38
|
+
end
|
39
|
+
@output << "\n\n"
|
40
|
+
|
41
|
+
print_threads
|
42
|
+
end
|
43
|
+
|
44
|
+
def print_threads
|
45
|
+
@result.threads.each do |thread_id, methods|
|
46
|
+
print_methods(thread_id, methods)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def convert(value)
|
51
|
+
(value * @value_scale).round
|
52
|
+
end
|
53
|
+
|
54
|
+
def file(method)
|
55
|
+
File.expand_path(method.source_file)
|
56
|
+
end
|
57
|
+
|
58
|
+
def name(method)
|
59
|
+
"#{method.klass_name}::#{method.method_name}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def print_methods(thread_id, methods)
|
63
|
+
methods.reverse_each do |method|
|
64
|
+
# Print out the file and method name
|
65
|
+
@output << "fl=#{file(method)}\n"
|
66
|
+
@output << "fn=#{name(method)}\n"
|
67
|
+
|
68
|
+
# Now print out the function line number and its self time
|
69
|
+
@output << "#{method.line} #{convert(method.self_time)}\n"
|
70
|
+
|
71
|
+
# Now print out all the children methods
|
72
|
+
method.children.each do |callee|
|
73
|
+
@output << "cfl=#{file(callee.target)}\n"
|
74
|
+
@output << "cfn=#{name(callee.target)}\n"
|
75
|
+
@output << "calls=#{callee.called} #{callee.line}\n"
|
76
|
+
|
77
|
+
# Print out total times here!
|
78
|
+
@output << "#{callee.line} #{convert(callee.total_time)}\n"
|
79
|
+
end
|
80
|
+
@output << "\n"
|
81
|
+
end
|
82
|
+
end #end print_methods
|
83
|
+
end # end class
|
84
|
+
end # end packages
|