ruby-prof 0.8.1-x86-mingw32 → 0.11.0.rc1-x86-mingw32
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 +89 -13
- data/LICENSE +4 -3
- data/{README → README.rdoc} +155 -162
- data/Rakefile +50 -123
- data/bin/ruby-prof +86 -47
- data/examples/empty.png +0 -0
- data/examples/graph.dot +106 -0
- data/examples/graph.png +0 -0
- data/examples/minus.png +0 -0
- data/examples/multi.flat.txt +23 -0
- data/examples/multi.graph.html +906 -0
- data/examples/multi.grind.dat +194 -0
- data/examples/multi.stack.html +573 -0
- data/examples/plus.png +0 -0
- data/examples/stack.html +573 -0
- data/ext/ruby_prof/extconf.rb +53 -0
- data/ext/ruby_prof/rp_call_info.c +369 -0
- data/ext/ruby_prof/rp_call_info.h +46 -0
- data/ext/ruby_prof/rp_measure.c +48 -0
- data/ext/ruby_prof/rp_measure.h +45 -0
- data/ext/ruby_prof/rp_measure_allocations.c +86 -0
- data/ext/ruby_prof/rp_measure_cpu_time.c +112 -0
- data/ext/ruby_prof/rp_measure_gc_runs.c +87 -0
- data/ext/ruby_prof/rp_measure_gc_time.c +73 -0
- data/ext/ruby_prof/rp_measure_memory.c +81 -0
- data/ext/ruby_prof/rp_measure_process_time.c +71 -0
- data/ext/ruby_prof/rp_measure_wall_time.c +42 -0
- data/ext/ruby_prof/rp_method.c +363 -0
- data/ext/ruby_prof/rp_method.h +55 -0
- data/ext/ruby_prof/rp_stack.c +61 -0
- data/ext/ruby_prof/rp_stack.h +40 -0
- data/ext/ruby_prof/rp_thread.c +113 -0
- data/ext/ruby_prof/rp_thread.h +20 -0
- data/ext/ruby_prof/ruby_prof.c +332 -1377
- data/ext/ruby_prof/ruby_prof.h +54 -188
- data/ext/ruby_prof/version.h +6 -3
- data/lib/1.8/ruby_prof.so +0 -0
- data/lib/1.9/ruby_prof.exp +0 -0
- data/lib/1.9/ruby_prof.ilk +0 -0
- data/lib/1.9/ruby_prof.lib +0 -0
- data/lib/1.9/ruby_prof.pdb +0 -0
- data/lib/1.9/ruby_prof.so +0 -0
- data/lib/ruby-prof.rb +32 -18
- data/lib/ruby-prof/abstract_printer.rb +15 -5
- data/lib/ruby-prof/aggregate_call_info.rb +11 -3
- data/lib/ruby-prof/call_info.rb +68 -1
- data/lib/ruby-prof/call_stack_printer.rb +775 -0
- data/lib/ruby-prof/call_tree_printer.rb +17 -9
- data/lib/ruby-prof/compatibility.rb +134 -0
- data/lib/ruby-prof/dot_printer.rb +152 -0
- data/lib/ruby-prof/empty.png +0 -0
- data/lib/ruby-prof/flat_printer.rb +23 -24
- data/lib/ruby-prof/flat_printer_with_line_numbers.rb +17 -21
- data/lib/ruby-prof/graph_html_printer.rb +69 -39
- data/lib/ruby-prof/graph_printer.rb +35 -35
- data/lib/ruby-prof/method_info.rb +26 -4
- data/lib/ruby-prof/minus.png +0 -0
- data/lib/ruby-prof/multi_printer.rb +56 -0
- data/lib/ruby-prof/plus.png +0 -0
- data/lib/ruby-prof/profile.rb +72 -0
- data/lib/ruby-prof/rack.rb +31 -0
- data/lib/ruby-prof/symbol_to_proc.rb +3 -1
- data/lib/ruby-prof/task.rb +20 -19
- data/lib/ruby-prof/test.rb +5 -3
- data/lib/ruby_prof.exp +0 -0
- data/lib/ruby_prof.ilk +0 -0
- data/lib/ruby_prof.lib +0 -0
- data/lib/ruby_prof.pdb +0 -0
- data/lib/ruby_prof.so +0 -0
- data/lib/unprof.rb +2 -0
- data/test/aggregate_test.rb +29 -14
- data/test/basic_test.rb +3 -251
- data/test/bug_test.rb +6 -0
- data/test/duplicate_names_test.rb +4 -4
- data/test/dynamic_method_test.rb +61 -0
- data/test/enumerable_test.rb +4 -4
- data/test/exceptions_test.rb +6 -5
- data/test/exclude_threads_test.rb +47 -47
- data/test/exec_test.rb +5 -5
- data/test/line_number_test.rb +16 -16
- data/test/measure_allocations_test.rb +25 -0
- data/test/measure_cpu_time_test.rb +212 -0
- data/test/measure_gc_runs_test.rb +29 -0
- data/test/measure_gc_time_test.rb +29 -0
- data/test/measure_memory_test.rb +36 -0
- data/test/measure_process_time_test.rb +205 -0
- data/test/measure_wall_time_test.rb +209 -0
- data/test/method_elimination_test.rb +74 -0
- data/test/module_test.rb +12 -21
- data/test/multi_printer_test.rb +81 -0
- data/test/no_method_class_test.rb +5 -3
- data/test/prime.rb +7 -10
- data/test/prime_test.rb +3 -3
- data/test/printers_test.rb +180 -54
- data/test/recursive_test.rb +34 -72
- data/test/singleton_test.rb +5 -4
- data/test/stack_printer_test.rb +73 -0
- data/test/stack_test.rb +7 -7
- data/test/start_stop_test.rb +23 -6
- data/test/test_helper.rb +81 -0
- data/test/test_suite.rb +35 -21
- data/test/thread_test.rb +40 -39
- data/test/unique_call_path_test.rb +6 -6
- metadata +106 -51
- data/ext/ruby_prof/measure_allocations.h +0 -58
- data/ext/ruby_prof/measure_cpu_time.h +0 -152
- data/ext/ruby_prof/measure_gc_runs.h +0 -76
- data/ext/ruby_prof/measure_gc_time.h +0 -57
- data/ext/ruby_prof/measure_memory.h +0 -101
- data/ext/ruby_prof/measure_process_time.h +0 -52
- data/ext/ruby_prof/measure_wall_time.h +0 -53
- data/ext/ruby_prof/mingw/Rakefile +0 -23
- data/ext/ruby_prof/mingw/build.rake +0 -38
- data/rails/environment/profile.rb +0 -24
- data/rails/example/example_test.rb +0 -9
- data/rails/profile_test_helper.rb +0 -21
- data/test/current_failures_windows +0 -8
- data/test/measurement_test.rb +0 -121
- data/test/ruby-prof-bin +0 -20
@@ -0,0 +1,81 @@
|
|
1
|
+
/* Copyright (C) 2005-2011 Shugo Maeda <shugo@ruby-lang.org> and Charlie Savage <cfis@savagexi.com>
|
2
|
+
Please see the LICENSE file for copyright and distribution information */
|
3
|
+
|
4
|
+
/* :nodoc: */
|
5
|
+
|
6
|
+
#include "ruby_prof.h"
|
7
|
+
|
8
|
+
static VALUE cMeasureMemory;
|
9
|
+
|
10
|
+
#if defined(HAVE_RB_GC_ALLOCATED_SIZE)
|
11
|
+
#define TOGGLE_GC_STATS 1
|
12
|
+
#define MEASURE_GC_TIME_ENABLED Qtrue
|
13
|
+
|
14
|
+
static double
|
15
|
+
measure_memory()
|
16
|
+
{
|
17
|
+
#if defined(HAVE_LONG_LONG)
|
18
|
+
return NUM2LL(rb_gc_allocated_size() / 1024);
|
19
|
+
#else
|
20
|
+
return NUM2ULONG(rb_gc_allocated_size() / 1024);
|
21
|
+
#endif
|
22
|
+
}
|
23
|
+
|
24
|
+
#elif defined(HAVE_RB_GC_MALLOC_ALLOCATED_SIZE)
|
25
|
+
|
26
|
+
#define MEASURE_MEMORY_ENABLED Qtrue
|
27
|
+
|
28
|
+
static double
|
29
|
+
measure_memory()
|
30
|
+
{
|
31
|
+
return rb_gc_malloc_allocated_size() / 1024;
|
32
|
+
}
|
33
|
+
|
34
|
+
|
35
|
+
#elif defined(HAVE_RB_HEAP_TOTAL_MEM)
|
36
|
+
|
37
|
+
#define MEASURE_MEMORY_ENABLED Qtrue
|
38
|
+
|
39
|
+
static double
|
40
|
+
measure_memory()
|
41
|
+
{
|
42
|
+
return rb_heap_total_mem() / 1024;
|
43
|
+
}
|
44
|
+
|
45
|
+
#else
|
46
|
+
|
47
|
+
#define MEASURE_MEMORY_ENABLED Qfalse
|
48
|
+
|
49
|
+
static double
|
50
|
+
measure_memory()
|
51
|
+
{
|
52
|
+
return 0;
|
53
|
+
}
|
54
|
+
|
55
|
+
#endif
|
56
|
+
|
57
|
+
prof_measurer_t* prof_measurer_memory()
|
58
|
+
{
|
59
|
+
prof_measurer_t* measure = ALLOC(prof_measurer_t);
|
60
|
+
measure->measure = measure_memory;
|
61
|
+
return measure;
|
62
|
+
}
|
63
|
+
|
64
|
+
/* call-seq:
|
65
|
+
measure_process_time -> float
|
66
|
+
|
67
|
+
Returns the process time.*/
|
68
|
+
static VALUE
|
69
|
+
prof_measure_memory(VALUE self)
|
70
|
+
{
|
71
|
+
return rb_float_new(measure_memory());
|
72
|
+
}
|
73
|
+
|
74
|
+
void rp_init_measure_memory()
|
75
|
+
{
|
76
|
+
rb_define_const(mProf, "MEMORY", INT2NUM(MEASURE_MEMORY));
|
77
|
+
rb_define_const(mProf, "MEMORY_ENABLED", MEASURE_MEMORY_ENABLED);
|
78
|
+
|
79
|
+
cMeasureMemory = rb_define_class_under(mMeasure, "Memory", rb_cObject);
|
80
|
+
rb_define_singleton_method(cMeasureMemory, "measure", prof_measure_memory, 0);
|
81
|
+
}
|
@@ -0,0 +1,71 @@
|
|
1
|
+
/* Copyright (C) 2005-2011 Shugo Maeda <shugo@ruby-lang.org> and Charlie Savage <cfis@savagexi.com>
|
2
|
+
Please see the LICENSE file for copyright and distribution information */
|
3
|
+
|
4
|
+
#include "ruby_prof.h"
|
5
|
+
#include <time.h>
|
6
|
+
|
7
|
+
static VALUE cMeasureProcessTime;
|
8
|
+
|
9
|
+
static double
|
10
|
+
measure_process_time()
|
11
|
+
{
|
12
|
+
#if defined(__linux__)
|
13
|
+
struct timespec clock;
|
14
|
+
clock_gettime(CLOCK_PROCESS_CPUTIME_ID , &clock);
|
15
|
+
return (clock.tv_sec * 1000000000 + clock.tv_nsec) / 1000000000.0;
|
16
|
+
#elif defined(_win32)
|
17
|
+
FILETIME createTime;
|
18
|
+
FILETIME exitTime;
|
19
|
+
FILETIME sysTime;
|
20
|
+
FILETIME cpuTime;
|
21
|
+
|
22
|
+
ULARGE_INTEGER sysTimeInt;
|
23
|
+
ULARGE_INTEGER cpuTimeInt;
|
24
|
+
ULONGLONG totalTime;
|
25
|
+
|
26
|
+
GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &sysTime, &cpuTime);
|
27
|
+
|
28
|
+
/* Doing this based on MSFT's recommendation in the FILETIME structure documentation at
|
29
|
+
http://msdn.microsoft.com/en-us/library/ms724284%28VS.85%29.aspx*/
|
30
|
+
|
31
|
+
sysTimeInt.LowPart = sysTime.dwLowDateTime;
|
32
|
+
sysTimeInt.HighPart = sysTime.dwHighDateTime;
|
33
|
+
cpuTimeInt.LowPart = cpuTime.dwLowDateTime;
|
34
|
+
cpuTimeInt.HighPart = cpuTime.dwHighDateTime;
|
35
|
+
|
36
|
+
totalTime = sysTimeInt.QuadPart + cpuTimeInt.QuadPart;
|
37
|
+
|
38
|
+
// Times are in 100-nanosecond time units. So instead of 10-9 use 10-7
|
39
|
+
return totalTime / 10000000.0;
|
40
|
+
#else
|
41
|
+
return ((double)clock()) / CLOCKS_PER_SEC;
|
42
|
+
#endif
|
43
|
+
}
|
44
|
+
|
45
|
+
/* call-seq:
|
46
|
+
measure_process_time -> float
|
47
|
+
|
48
|
+
Returns the process time.*/
|
49
|
+
static VALUE
|
50
|
+
prof_measure_process_time(VALUE self)
|
51
|
+
{
|
52
|
+
return rb_float_new(measure_process_time());
|
53
|
+
}
|
54
|
+
|
55
|
+
prof_measurer_t* prof_measurer_process_time()
|
56
|
+
{
|
57
|
+
prof_measurer_t* measure = ALLOC(prof_measurer_t);
|
58
|
+
measure->measure = measure_process_time;
|
59
|
+
return measure;
|
60
|
+
}
|
61
|
+
|
62
|
+
|
63
|
+
void rp_init_measure_process_time()
|
64
|
+
{
|
65
|
+
rb_define_const(mProf, "CLOCKS_PER_SEC", INT2NUM(CLOCKS_PER_SEC));
|
66
|
+
rb_define_const(mProf, "PROCESS_TIME", INT2NUM(MEASURE_PROCESS_TIME));
|
67
|
+
rb_define_const(mProf, "PROCESS_TIME_ENABLED", Qtrue);
|
68
|
+
|
69
|
+
cMeasureProcessTime = rb_define_class_under(mMeasure, "ProcessTime", rb_cObject);
|
70
|
+
rb_define_singleton_method(cMeasureProcessTime, "measure", prof_measure_process_time, 0);
|
71
|
+
}
|
@@ -0,0 +1,42 @@
|
|
1
|
+
/* Copyright (C) 2005-2011 Shugo Maeda <shugo@ruby-lang.org> and Charlie Savage <cfis@savagexi.com>
|
2
|
+
Please see the LICENSE file for copyright and distribution information */
|
3
|
+
|
4
|
+
/* :nodoc: */
|
5
|
+
#include "ruby_prof.h"
|
6
|
+
|
7
|
+
static VALUE cMeasureWallTime;
|
8
|
+
|
9
|
+
static double
|
10
|
+
measure_wall_time()
|
11
|
+
{
|
12
|
+
struct timeval tv;
|
13
|
+
gettimeofday(&tv, NULL);
|
14
|
+
return (tv.tv_sec * 1000000 + tv.tv_usec) / 1000000.0;
|
15
|
+
}
|
16
|
+
|
17
|
+
prof_measurer_t* prof_measurer_wall_time()
|
18
|
+
{
|
19
|
+
prof_measurer_t* measure = ALLOC(prof_measurer_t);
|
20
|
+
measure->measure = measure_wall_time;
|
21
|
+
return measure;
|
22
|
+
}
|
23
|
+
|
24
|
+
/* Document-method: prof_measure_wall_time
|
25
|
+
call-seq:
|
26
|
+
measure_wall_time -> float
|
27
|
+
|
28
|
+
Returns the wall time.*/
|
29
|
+
static VALUE
|
30
|
+
prof_measure_wall_time(VALUE self)
|
31
|
+
{
|
32
|
+
return rb_float_new(measure_wall_time());
|
33
|
+
}
|
34
|
+
|
35
|
+
void rp_init_measure_wall_time()
|
36
|
+
{
|
37
|
+
rb_define_const(mProf, "WALL_TIME", INT2NUM(MEASURE_WALL_TIME));
|
38
|
+
rb_define_const(mProf, "WALL_TIME_ENABLED", Qtrue);
|
39
|
+
|
40
|
+
cMeasureWallTime = rb_define_class_under(mMeasure, "WallTime", rb_cObject);
|
41
|
+
rb_define_singleton_method(cMeasureWallTime, "measure", prof_measure_wall_time, 0);
|
42
|
+
}
|
@@ -0,0 +1,363 @@
|
|
1
|
+
/* Copyright (C) 2005-2011 Shugo Maeda <shugo@ruby-lang.org> and Charlie Savage <cfis@savagexi.com>
|
2
|
+
Please see the LICENSE file for copyright and distribution information */
|
3
|
+
|
4
|
+
#include "ruby_prof.h"
|
5
|
+
|
6
|
+
VALUE cMethodInfo;
|
7
|
+
|
8
|
+
/* ================ Helper Functions =================*/
|
9
|
+
static VALUE
|
10
|
+
figure_singleton_name(VALUE klass)
|
11
|
+
{
|
12
|
+
VALUE result = Qnil;
|
13
|
+
|
14
|
+
/* We have come across a singleton object. First
|
15
|
+
figure out what it is attached to.*/
|
16
|
+
VALUE attached = rb_iv_get(klass, "__attached__");
|
17
|
+
|
18
|
+
/* Is this a singleton class acting as a metaclass? */
|
19
|
+
if (BUILTIN_TYPE(attached) == T_CLASS)
|
20
|
+
{
|
21
|
+
result = rb_str_new2("<Class::");
|
22
|
+
rb_str_append(result, rb_inspect(attached));
|
23
|
+
rb_str_cat2(result, ">");
|
24
|
+
}
|
25
|
+
|
26
|
+
/* Is this for singleton methods on a module? */
|
27
|
+
else if (BUILTIN_TYPE(attached) == T_MODULE)
|
28
|
+
{
|
29
|
+
result = rb_str_new2("<Module::");
|
30
|
+
rb_str_append(result, rb_inspect(attached));
|
31
|
+
rb_str_cat2(result, ">");
|
32
|
+
}
|
33
|
+
|
34
|
+
/* Is this for singleton methods on an object? */
|
35
|
+
else if (BUILTIN_TYPE(attached) == T_OBJECT)
|
36
|
+
{
|
37
|
+
/* Make sure to get the super class so that we don't
|
38
|
+
mistakenly grab a T_ICLASS which would lead to
|
39
|
+
unknown method errors. */
|
40
|
+
#ifdef HAVE_RB_CLASS_SUPERCLASS
|
41
|
+
// 1.9.3
|
42
|
+
VALUE super = rb_class_superclass(klass);
|
43
|
+
#else
|
44
|
+
# ifdef RCLASS_SUPER
|
45
|
+
VALUE super = rb_class_real(RCLASS_SUPER(klass));
|
46
|
+
# else
|
47
|
+
VALUE super = rb_class_real(RCLASS(klass)->super);
|
48
|
+
# endif
|
49
|
+
#endif
|
50
|
+
result = rb_str_new2("<Object::");
|
51
|
+
rb_str_append(result, rb_inspect(super));
|
52
|
+
rb_str_cat2(result, ">");
|
53
|
+
}
|
54
|
+
|
55
|
+
/* Ok, this could be other things like an array made put onto
|
56
|
+
a singleton object (yeah, it happens, see the singleton
|
57
|
+
objects test case). */
|
58
|
+
else
|
59
|
+
{
|
60
|
+
result = rb_inspect(klass);
|
61
|
+
}
|
62
|
+
|
63
|
+
return result;
|
64
|
+
}
|
65
|
+
|
66
|
+
static VALUE
|
67
|
+
klass_name(VALUE klass)
|
68
|
+
{
|
69
|
+
VALUE result = Qnil;
|
70
|
+
|
71
|
+
if (klass == 0 || klass == Qnil)
|
72
|
+
{
|
73
|
+
result = rb_str_new2("Global");
|
74
|
+
}
|
75
|
+
else if (BUILTIN_TYPE(klass) == T_MODULE)
|
76
|
+
{
|
77
|
+
result = rb_inspect(klass);
|
78
|
+
}
|
79
|
+
else if (BUILTIN_TYPE(klass) == T_CLASS && FL_TEST(klass, FL_SINGLETON))
|
80
|
+
{
|
81
|
+
result = figure_singleton_name(klass);
|
82
|
+
}
|
83
|
+
else if (BUILTIN_TYPE(klass) == T_CLASS)
|
84
|
+
{
|
85
|
+
result = rb_inspect(klass);
|
86
|
+
}
|
87
|
+
else
|
88
|
+
{
|
89
|
+
/* Should never happen. */
|
90
|
+
result = rb_str_new2("Unknown");
|
91
|
+
}
|
92
|
+
|
93
|
+
return result;
|
94
|
+
}
|
95
|
+
|
96
|
+
static VALUE
|
97
|
+
method_name(ID mid)
|
98
|
+
{
|
99
|
+
VALUE result;
|
100
|
+
|
101
|
+
if (mid == ID_ALLOCATOR)
|
102
|
+
result = rb_str_new2("allocate");
|
103
|
+
else if (mid == 0)
|
104
|
+
result = rb_str_new2("[No method]");
|
105
|
+
else
|
106
|
+
result = rb_String(ID2SYM(mid));
|
107
|
+
|
108
|
+
return result;
|
109
|
+
}
|
110
|
+
|
111
|
+
static VALUE
|
112
|
+
full_name(VALUE klass, ID mid)
|
113
|
+
{
|
114
|
+
VALUE result = klass_name(klass);
|
115
|
+
rb_str_cat2(result, "#");
|
116
|
+
rb_str_append(result, method_name(mid));
|
117
|
+
|
118
|
+
return result;
|
119
|
+
}
|
120
|
+
|
121
|
+
|
122
|
+
/* ================ Method Table =================*/
|
123
|
+
int
|
124
|
+
method_table_cmp(prof_method_key_t *key1, prof_method_key_t *key2)
|
125
|
+
{
|
126
|
+
return (key1->klass != key2->klass) || (key1->mid != key2->mid);
|
127
|
+
}
|
128
|
+
|
129
|
+
st_index_t
|
130
|
+
method_table_hash(prof_method_key_t *key)
|
131
|
+
{
|
132
|
+
return key->key;
|
133
|
+
}
|
134
|
+
|
135
|
+
struct st_hash_type type_method_hash = {
|
136
|
+
method_table_cmp,
|
137
|
+
method_table_hash
|
138
|
+
};
|
139
|
+
|
140
|
+
st_table *
|
141
|
+
method_table_create()
|
142
|
+
{
|
143
|
+
return st_init_table(&type_method_hash);
|
144
|
+
}
|
145
|
+
|
146
|
+
size_t
|
147
|
+
method_table_insert(st_table *table, const prof_method_key_t *key, prof_method_t *val)
|
148
|
+
{
|
149
|
+
return st_insert(table, (st_data_t) key, (st_data_t) val);
|
150
|
+
}
|
151
|
+
|
152
|
+
prof_method_t *
|
153
|
+
method_table_lookup(st_table *table, const prof_method_key_t* key)
|
154
|
+
{
|
155
|
+
st_data_t val;
|
156
|
+
if (st_lookup(table, (st_data_t)key, &val))
|
157
|
+
{
|
158
|
+
return (prof_method_t *) val;
|
159
|
+
}
|
160
|
+
else
|
161
|
+
{
|
162
|
+
return NULL;
|
163
|
+
}
|
164
|
+
}
|
165
|
+
|
166
|
+
void
|
167
|
+
method_table_free(st_table *table)
|
168
|
+
{
|
169
|
+
/* Don't free the contents since they are wrapped by
|
170
|
+
Ruby objects! */
|
171
|
+
st_free_table(table);
|
172
|
+
}
|
173
|
+
|
174
|
+
|
175
|
+
/* ================ Method Info =================*/
|
176
|
+
/* Document-class: RubyProf::MethodInfo
|
177
|
+
The RubyProf::MethodInfo class stores profiling data for a method.
|
178
|
+
One instance of the RubyProf::MethodInfo class is created per method
|
179
|
+
called per thread. Thus, if a method is called in two different
|
180
|
+
thread then there will be two RubyProf::MethodInfo objects
|
181
|
+
created. RubyProf::MethodInfo objects can be accessed via
|
182
|
+
the RubyProf::Result object.
|
183
|
+
*/
|
184
|
+
|
185
|
+
prof_method_t*
|
186
|
+
prof_method_create(prof_method_key_t *key, const char* source_file, int line)
|
187
|
+
{
|
188
|
+
prof_method_t *result = ALLOC(prof_method_t);
|
189
|
+
result->object = Qnil;
|
190
|
+
result->key = ALLOC(prof_method_key_t);
|
191
|
+
method_key(result->key, key->klass, key->mid);
|
192
|
+
|
193
|
+
result->call_infos = prof_call_infos_create();
|
194
|
+
|
195
|
+
if (source_file != NULL)
|
196
|
+
{
|
197
|
+
size_t len = strlen(source_file) + 1;
|
198
|
+
char *buffer = ALLOC_N(char, len);
|
199
|
+
|
200
|
+
MEMCPY(buffer, source_file, char, len);
|
201
|
+
result->source_file = buffer;
|
202
|
+
}
|
203
|
+
else
|
204
|
+
{
|
205
|
+
result->source_file = source_file;
|
206
|
+
}
|
207
|
+
result->line = line;
|
208
|
+
|
209
|
+
return result;
|
210
|
+
}
|
211
|
+
|
212
|
+
void
|
213
|
+
prof_method_mark(prof_method_t *method)
|
214
|
+
{
|
215
|
+
rb_gc_mark(method->call_infos->object);
|
216
|
+
rb_gc_mark(method->key->klass);
|
217
|
+
}
|
218
|
+
|
219
|
+
static void
|
220
|
+
prof_method_free(prof_method_t *method)
|
221
|
+
{
|
222
|
+
if (method->source_file)
|
223
|
+
{
|
224
|
+
xfree((char*)method->source_file);
|
225
|
+
}
|
226
|
+
|
227
|
+
prof_call_infos_free(method->call_infos);
|
228
|
+
xfree(method->key);
|
229
|
+
xfree(method);
|
230
|
+
}
|
231
|
+
|
232
|
+
VALUE
|
233
|
+
prof_method_wrap(prof_method_t *result)
|
234
|
+
{
|
235
|
+
if (result->object == Qnil)
|
236
|
+
{
|
237
|
+
result->object = Data_Wrap_Struct(cMethodInfo, prof_method_mark, prof_method_free, result);
|
238
|
+
}
|
239
|
+
return result->object;
|
240
|
+
}
|
241
|
+
|
242
|
+
static prof_method_t *
|
243
|
+
get_prof_method(VALUE obj)
|
244
|
+
{
|
245
|
+
return (prof_method_t *) DATA_PTR(obj);
|
246
|
+
}
|
247
|
+
|
248
|
+
/* call-seq:
|
249
|
+
line_no -> int
|
250
|
+
|
251
|
+
returns the line number of the method */
|
252
|
+
static VALUE
|
253
|
+
prof_method_line(VALUE self)
|
254
|
+
{
|
255
|
+
return rb_int_new(get_prof_method(self)->line);
|
256
|
+
}
|
257
|
+
|
258
|
+
/* call-seq:
|
259
|
+
source_file => string
|
260
|
+
|
261
|
+
return the source file of the method
|
262
|
+
*/
|
263
|
+
static VALUE prof_method_source_file(VALUE self)
|
264
|
+
{
|
265
|
+
const char* sf = get_prof_method(self)->source_file;
|
266
|
+
if(!sf)
|
267
|
+
{
|
268
|
+
return rb_str_new2("ruby_runtime");
|
269
|
+
}
|
270
|
+
else
|
271
|
+
{
|
272
|
+
return rb_str_new2(sf);
|
273
|
+
}
|
274
|
+
}
|
275
|
+
|
276
|
+
|
277
|
+
/* call-seq:
|
278
|
+
method_class -> klass
|
279
|
+
|
280
|
+
Returns the Ruby klass that owns this method. */
|
281
|
+
static VALUE
|
282
|
+
prof_method_klass(VALUE self)
|
283
|
+
{
|
284
|
+
prof_method_t *result = get_prof_method(self);
|
285
|
+
return result->key->klass;
|
286
|
+
}
|
287
|
+
|
288
|
+
/* call-seq:
|
289
|
+
method_id -> ID
|
290
|
+
|
291
|
+
Returns the id of this method. */
|
292
|
+
static VALUE
|
293
|
+
prof_method_id(VALUE self)
|
294
|
+
{
|
295
|
+
prof_method_t *result = get_prof_method(self);
|
296
|
+
return ID2SYM(result->key->mid);
|
297
|
+
}
|
298
|
+
|
299
|
+
/* call-seq:
|
300
|
+
klass_name -> string
|
301
|
+
|
302
|
+
Returns the name of this method's class. Singleton classes
|
303
|
+
will have the form <Object::Object>. */
|
304
|
+
|
305
|
+
static VALUE
|
306
|
+
prof_klass_name(VALUE self)
|
307
|
+
{
|
308
|
+
prof_method_t *method = get_prof_method(self);
|
309
|
+
return klass_name(method->key->klass);
|
310
|
+
}
|
311
|
+
|
312
|
+
/* call-seq:
|
313
|
+
method_name -> string
|
314
|
+
|
315
|
+
Returns the name of this method in the format Object#method. Singletons
|
316
|
+
methods will be returned in the format <Object::Object>#method.*/
|
317
|
+
|
318
|
+
static VALUE
|
319
|
+
prof_method_name(VALUE self)
|
320
|
+
{
|
321
|
+
prof_method_t *method = get_prof_method(self);
|
322
|
+
return method_name(method->key->mid);
|
323
|
+
}
|
324
|
+
|
325
|
+
/* call-seq:
|
326
|
+
full_name -> string
|
327
|
+
|
328
|
+
Returns the full name of this method in the format Object#method.*/
|
329
|
+
|
330
|
+
static VALUE
|
331
|
+
prof_full_name(VALUE self)
|
332
|
+
{
|
333
|
+
prof_method_t *method = get_prof_method(self);
|
334
|
+
return full_name(method->key->klass, method->key->mid);
|
335
|
+
}
|
336
|
+
|
337
|
+
/* call-seq:
|
338
|
+
call_infos -> Array of call_info
|
339
|
+
|
340
|
+
Returns an array of call info objects that contain profiling information
|
341
|
+
about the current method.*/
|
342
|
+
static VALUE
|
343
|
+
prof_method_call_infos(VALUE self)
|
344
|
+
{
|
345
|
+
prof_method_t *method = get_prof_method(self);
|
346
|
+
return prof_call_infos_wrap(method->call_infos);
|
347
|
+
}
|
348
|
+
|
349
|
+
void rp_init_method_info()
|
350
|
+
{
|
351
|
+
/* MethodInfo */
|
352
|
+
cMethodInfo = rb_define_class_under(mProf, "MethodInfo", rb_cObject);
|
353
|
+
rb_undef_method(CLASS_OF(cMethodInfo), "new");
|
354
|
+
|
355
|
+
rb_define_method(cMethodInfo, "klass", prof_method_klass, 0);
|
356
|
+
rb_define_method(cMethodInfo, "klass_name", prof_klass_name, 0);
|
357
|
+
rb_define_method(cMethodInfo, "method_name", prof_method_name, 0);
|
358
|
+
rb_define_method(cMethodInfo, "full_name", prof_full_name, 0);
|
359
|
+
rb_define_method(cMethodInfo, "method_id", prof_method_id, 0);
|
360
|
+
rb_define_method(cMethodInfo, "source_file", prof_method_source_file,0);
|
361
|
+
rb_define_method(cMethodInfo, "line", prof_method_line, 0);
|
362
|
+
rb_define_method(cMethodInfo, "call_infos", prof_method_call_infos, 0);
|
363
|
+
}
|