ruby-prof 0.11.0.rc1-x86-mingw32 → 0.11.0.rc2-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 +20 -5
- data/README.rdoc +10 -3
- data/ext/ruby_prof/rp_call_info.c +108 -79
- data/ext/ruby_prof/rp_call_info.h +1 -0
- data/ext/ruby_prof/rp_measure_cpu_time.c +111 -111
- data/ext/ruby_prof/rp_measure_gc_runs.c +1 -1
- data/ext/ruby_prof/rp_measure_memory.c +1 -1
- data/ext/ruby_prof/rp_measure_process_time.c +71 -71
- data/ext/ruby_prof/rp_measure_wall_time.c +1 -1
- data/ext/ruby_prof/rp_method.c +143 -73
- data/ext/ruby_prof/rp_method.h +7 -4
- data/ext/ruby_prof/rp_stack.c +16 -1
- data/ext/ruby_prof/rp_stack.h +4 -1
- data/ext/ruby_prof/rp_thread.c +165 -35
- data/ext/ruby_prof/rp_thread.h +8 -2
- data/ext/ruby_prof/ruby_prof.c +164 -171
- data/ext/ruby_prof/ruby_prof.h +53 -54
- data/ext/ruby_prof/vc/ruby_prof.sln +26 -0
- data/ext/ruby_prof/vc/ruby_prof.vcxproj +109 -0
- data/ext/ruby_prof/vc/ruby_prof_18.vcxproj +105 -0
- data/lib/1.8/ruby_prof.so +0 -0
- data/lib/1.9/ruby_prof.so +0 -0
- data/lib/ruby-prof/aggregate_call_info.rb +9 -7
- data/lib/ruby-prof/call_info.rb +2 -27
- data/lib/ruby-prof/call_info_visitor.rb +42 -0
- data/lib/ruby-prof/{empty.png → images/empty.png} +0 -0
- data/lib/ruby-prof/{minus.png → images/minus.png} +0 -0
- data/lib/ruby-prof/{plus.png → images/plus.png} +0 -0
- data/lib/ruby-prof/method_info.rb +13 -15
- data/lib/ruby-prof/{abstract_printer.rb → printers/abstract_printer.rb} +36 -2
- data/lib/ruby-prof/printers/call_info_printer.rb +40 -0
- data/lib/ruby-prof/{call_stack_printer.rb → printers/call_stack_printer.rb} +11 -16
- data/lib/ruby-prof/{call_tree_printer.rb → printers/call_tree_printer.rb} +4 -4
- data/lib/ruby-prof/{dot_printer.rb → printers/dot_printer.rb} +11 -31
- data/lib/ruby-prof/{flat_printer.rb → printers/flat_printer.rb} +26 -35
- data/lib/ruby-prof/{flat_printer_with_line_numbers.rb → printers/flat_printer_with_line_numbers.rb} +14 -25
- data/lib/ruby-prof/printers/graph_html_printer.rb +248 -0
- data/lib/ruby-prof/{graph_printer.rb → printers/graph_printer.rb} +31 -73
- data/lib/ruby-prof/{multi_printer.rb → printers/multi_printer.rb} +0 -0
- data/lib/ruby-prof/profile.rb +27 -22
- data/lib/ruby-prof/rack.rb +22 -12
- data/ruby-prof.gemspec +58 -0
- data/test/aggregate_test.rb +6 -6
- data/test/call_info_visitor_test.rb +31 -0
- data/test/duplicate_names_test.rb +1 -1
- data/test/dynamic_method_test.rb +1 -1
- data/test/enumerable_test.rb +1 -1
- data/test/exclude_threads_test.rb +2 -2
- data/test/gc_test.rb +35 -0
- data/test/line_number_test.rb +2 -2
- data/test/measure_cpu_time_test.rb +5 -5
- data/test/measure_process_time_test.rb +5 -5
- data/test/measure_wall_time_test.rb +5 -5
- data/test/method_elimination_test.rb +3 -3
- data/test/module_test.rb +1 -1
- data/test/no_method_class_test.rb +1 -1
- data/test/printers_test.rb +16 -8
- data/test/recursive_test.rb +115 -91
- data/test/stack_test.rb +1 -1
- data/test/start_stop_test.rb +13 -13
- data/test/summarize_test.rb +48 -0
- data/test/test_suite.rb +1 -0
- data/test/thread_test.rb +16 -12
- data/test/unique_call_path_test.rb +10 -10
- metadata +65 -85
- 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/ruby-prof.rb +0 -70
- data/lib/ruby-prof/graph_html_printer.rb +0 -286
- data/lib/ruby-prof/symbol_to_proc.rb +0 -10
- 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 +0 -10
- data/test/do_nothing.rb +0 -0
data/CHANGES
CHANGED
@@ -1,13 +1,28 @@
|
|
1
|
+
0.11.0.rc2 (2012-03-25)
|
2
|
+
======================
|
3
|
+
* Lots of improvements to Rack handler - this can be used to profile requests
|
4
|
+
in Rails and other rack-based ruby web frameworks (Charlie Savage).
|
5
|
+
* Reimplemented handling of recursive calls using CallInfoVisitor (Charlie Savage).
|
6
|
+
* Fix bug where child times were not correctly reported in complicated
|
7
|
+
call graphs with recursion like in frameworks like Rails (Charlie Savage).
|
8
|
+
* Add in recursive call information to Flat, Graph and Graph HTML reports (Charlie Savage).
|
9
|
+
* Add in new thread class add added RubyProf::Thread#top_method to
|
10
|
+
make report generation easier (Charlie Savage).
|
11
|
+
* Add in CallInfoVisitor class to make it easy to iterate over a call graph (Charlie Savage).
|
12
|
+
* Add in CallInfoPrinter to make it visualize RubyProf's internal call graphs (Charlie Savage).
|
13
|
+
* Significant updates to documentation (Charlie Savage).
|
14
|
+
* More c code cleanup (Charlie Savage).
|
15
|
+
|
1
16
|
0.11.0.rc1 (2012-03-24)
|
2
17
|
======================
|
18
|
+
* Big internal refactoring of C code to make RubyProf easier to understand and extend (Charlie Savage).
|
19
|
+
* Profile results are now returned as instances of a new class RubyProf::Profile. The old api
|
20
|
+
is supported via a compatability layer that at some point will be deprecated. (Charlie Savage).
|
3
21
|
* On Windows, use QueryPerformanceCounter and QueryPerformanceFrequency to measure CPU time instead
|
4
22
|
of rdtsc. This change is based on Microsoft's recommendation (Charlie Savage).
|
5
23
|
* On Windows use GetProcessTimes to return real PROCESS_TIME times instead of wall times (Charlie Savage).
|
6
|
-
*
|
7
|
-
*
|
8
|
-
is supported via a compatability layer that at some point will be deprecated. (Charlie Savage).
|
9
|
-
* Split out tests for cpu_time, process_time and wall_time into separate files (Charlie Savage).
|
10
|
-
* Dropped support for Ruby 1.8.4 and 1.8.6 - does anybody still use these? (Charlie Savage).
|
24
|
+
* Split out tests for each time of measurement (cpu_time, process_time, etc.) (Charlie Savage).
|
25
|
+
* Dropped support for Ruby 1.8.4 and 1.8.6 and 1.9.0 (Charlie Savage).
|
11
26
|
* Added support for sorting results by total, self, wait and child times (Jan Suchal)
|
12
27
|
* Added tests for sorting behaviour & removed options from constructor to print method (Jan Suchal)
|
13
28
|
* Fix line number tests due to changes at top of file (Charlie Savage).
|
data/README.rdoc
CHANGED
@@ -187,9 +187,16 @@ So to profile Rails:
|
|
187
187
|
|
188
188
|
1. Create a new profile.rb environment. Make sure to turn on cache_classes
|
189
189
|
and cache_template_loading. Otherwise your profiling results will be
|
190
|
-
overwhelemed by the time Rails spends loading required files.
|
190
|
+
overwhelemed by the time Rails spends loading required files. You should
|
191
|
+
likely turn off caching.
|
191
192
|
|
192
|
-
2. Add the ruby
|
193
|
+
2. Add the ruby-prof to your gemfile:
|
194
|
+
|
195
|
+
group :profile do
|
196
|
+
gem 'ruby-prof'
|
197
|
+
end
|
198
|
+
|
199
|
+
3. Add the ruby prof rack adapter to your middleware stack. One way to
|
193
200
|
do this is by adding the following code to config.ru:
|
194
201
|
|
195
202
|
if Rails.env.profile?
|
@@ -199,7 +206,7 @@ do this is by adding the following code to config.ru:
|
|
199
206
|
The path is where you want profiling results to be stored. By default the
|
200
207
|
rack adapter will generate a html call graph report and flat text report.
|
201
208
|
|
202
|
-
|
209
|
+
4. Now make a request to your running server. New profiling information will
|
203
210
|
be generated for each request. Note that each request will overwrite
|
204
211
|
the profiling reports created by the previous request!
|
205
212
|
|
@@ -7,45 +7,13 @@
|
|
7
7
|
|
8
8
|
VALUE cCallInfo;
|
9
9
|
|
10
|
-
/* ======= Call Info ========*/
|
11
|
-
st_table *
|
12
|
-
call_info_table_create()
|
13
|
-
{
|
14
|
-
return st_init_table(&type_method_hash);
|
15
|
-
}
|
16
|
-
|
17
|
-
size_t
|
18
|
-
call_info_table_insert(st_table *table, const prof_method_key_t *key, prof_call_info_t *val)
|
19
|
-
{
|
20
|
-
return st_insert(table, (st_data_t) key, (st_data_t) val);
|
21
|
-
}
|
22
|
-
|
23
|
-
prof_call_info_t *
|
24
|
-
call_info_table_lookup(st_table *table, const prof_method_key_t *key)
|
25
|
-
{
|
26
|
-
st_data_t val;
|
27
|
-
if (st_lookup(table, (st_data_t) key, &val))
|
28
|
-
{
|
29
|
-
return (prof_call_info_t *) val;
|
30
|
-
}
|
31
|
-
else
|
32
|
-
{
|
33
|
-
return NULL;
|
34
|
-
}
|
35
|
-
}
|
36
10
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
st_free_table(table);
|
41
|
-
}
|
11
|
+
// Forward declarations
|
12
|
+
st_table * call_info_table_create();
|
13
|
+
void call_info_table_free(st_table *table);
|
42
14
|
|
43
|
-
/* Document-class: RubyProf::CallInfo
|
44
|
-
RubyProf::CallInfo is a helper class used by RubyProf::MethodInfo
|
45
|
-
to keep track of which child methods were called and how long
|
46
|
-
they took to execute. */
|
47
15
|
|
48
|
-
/*
|
16
|
+
/* ======= prof_call_info_t ========*/
|
49
17
|
prof_call_info_t *
|
50
18
|
prof_call_info_create(prof_method_t* method, prof_call_info_t* parent)
|
51
19
|
{
|
@@ -65,35 +33,33 @@ prof_call_info_create(prof_method_t* method, prof_call_info_t* parent)
|
|
65
33
|
}
|
66
34
|
|
67
35
|
static void
|
68
|
-
|
36
|
+
prof_call_info_free(prof_call_info_t *call_info)
|
69
37
|
{
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
rb_gc_mark(call_info->children);
|
78
|
-
if (call_info->parent) {
|
79
|
-
VALUE parent = call_info->parent->object;
|
80
|
-
if (NIL_P(parent)) {
|
81
|
-
prof_call_info_mark(call_info->parent);
|
38
|
+
/* Has this thread object been accessed by Ruby? If
|
39
|
+
yes clean it up so to avoid a segmentation fault. */
|
40
|
+
if (call_info->object != Qnil)
|
41
|
+
{
|
42
|
+
RDATA(call_info->object)->data = NULL;
|
43
|
+
RDATA(call_info->object)->dfree = NULL;
|
44
|
+
RDATA(call_info->object)->dmark = NULL;
|
82
45
|
}
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
46
|
+
call_info->object = Qnil;
|
47
|
+
|
48
|
+
call_info_table_free(call_info->call_infos);
|
49
|
+
xfree(call_info);
|
87
50
|
}
|
88
51
|
|
89
52
|
static void
|
90
|
-
|
53
|
+
prof_call_info_mark(prof_call_info_t *call_info)
|
91
54
|
{
|
92
|
-
|
93
|
-
|
55
|
+
if (call_info->object)
|
56
|
+
rb_gc_mark(call_info->children);
|
57
|
+
|
58
|
+
if (call_info->children)
|
59
|
+
rb_gc_mark(call_info->children);
|
94
60
|
}
|
95
61
|
|
96
|
-
|
62
|
+
VALUE
|
97
63
|
prof_call_info_wrap(prof_call_info_t *call_info)
|
98
64
|
{
|
99
65
|
if (call_info->object == Qnil)
|
@@ -104,17 +70,68 @@ prof_call_info_wrap(prof_call_info_t *call_info)
|
|
104
70
|
}
|
105
71
|
|
106
72
|
static prof_call_info_t *
|
107
|
-
|
73
|
+
prof_get_call_info(VALUE self)
|
74
|
+
{
|
75
|
+
/* Can't use Data_Get_Struct because that triggers the event hook
|
76
|
+
ending up in endless recursion. */
|
77
|
+
prof_call_info_t* result = DATA_PTR(self);
|
78
|
+
|
79
|
+
if (!result)
|
80
|
+
rb_raise(rb_eRuntimeError, "This RubyProf::CallInfo instance has already been freed, likely because its profile has been freed.");
|
81
|
+
|
82
|
+
return result;
|
83
|
+
}
|
84
|
+
|
85
|
+
/* ======= Call Info Table ========*/
|
86
|
+
st_table *
|
87
|
+
call_info_table_create()
|
88
|
+
{
|
89
|
+
return st_init_table(&type_method_hash);
|
90
|
+
}
|
91
|
+
|
92
|
+
/*static int
|
93
|
+
call_info_table_free_iterator(st_data_t key, st_data_t value, st_data_t dummy)
|
94
|
+
{
|
95
|
+
prof_call_info_free((prof_call_info_t*)value);
|
96
|
+
return ST_CONTINUE;
|
97
|
+
}*/
|
98
|
+
|
99
|
+
void
|
100
|
+
call_info_table_free(st_table *table)
|
101
|
+
{
|
102
|
+
//st_foreach(table, call_info_table_free_iterator, 0);
|
103
|
+
st_free_table(table);
|
104
|
+
}
|
105
|
+
|
106
|
+
size_t
|
107
|
+
call_info_table_insert(st_table *table, const prof_method_key_t *key, prof_call_info_t *val)
|
108
|
+
{
|
109
|
+
return st_insert(table, (st_data_t) key, (st_data_t) val);
|
110
|
+
}
|
111
|
+
|
112
|
+
prof_call_info_t *
|
113
|
+
call_info_table_lookup(st_table *table, const prof_method_key_t *key)
|
108
114
|
{
|
109
|
-
|
115
|
+
st_data_t val;
|
116
|
+
if (st_lookup(table, (st_data_t) key, &val))
|
110
117
|
{
|
111
|
-
|
112
|
-
|
118
|
+
return (prof_call_info_t *) val;
|
119
|
+
}
|
120
|
+
else
|
121
|
+
{
|
122
|
+
return NULL;
|
113
123
|
}
|
114
|
-
return (prof_call_info_t *) DATA_PTR(obj);
|
115
124
|
}
|
116
125
|
|
117
126
|
|
127
|
+
/* ======= RubyProf::CallInfo ========*/
|
128
|
+
|
129
|
+
/* Document-class: RubyProf::CallInfo
|
130
|
+
RubyProf::CallInfo is a helper class used by RubyProf::MethodInfo
|
131
|
+
to keep track of which child methods were called and how long
|
132
|
+
they took to execute. */
|
133
|
+
|
134
|
+
|
118
135
|
/* call-seq:
|
119
136
|
called -> MethodInfo
|
120
137
|
|
@@ -126,7 +143,7 @@ prof_call_info_target(VALUE self)
|
|
126
143
|
about the GC. We will wrap the method_info but provide no
|
127
144
|
free method so the underlying object is not freed twice! */
|
128
145
|
|
129
|
-
prof_call_info_t *result =
|
146
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
130
147
|
return prof_method_wrap(result->target);
|
131
148
|
}
|
132
149
|
|
@@ -137,7 +154,7 @@ Returns the total amount of times this method was called. */
|
|
137
154
|
static VALUE
|
138
155
|
prof_call_info_called(VALUE self)
|
139
156
|
{
|
140
|
-
prof_call_info_t *result =
|
157
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
141
158
|
return INT2NUM(result->called);
|
142
159
|
}
|
143
160
|
|
@@ -148,11 +165,22 @@ Sets the call count to n. */
|
|
148
165
|
static VALUE
|
149
166
|
prof_call_info_set_called(VALUE self, VALUE called)
|
150
167
|
{
|
151
|
-
prof_call_info_t *result =
|
168
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
152
169
|
result->called = NUM2INT(called);
|
153
170
|
return called;
|
154
171
|
}
|
155
172
|
|
173
|
+
/* call-seq:
|
174
|
+
depth -> int
|
175
|
+
|
176
|
+
returns the depth of this call info in the call graph */
|
177
|
+
static VALUE
|
178
|
+
prof_call_info_depth(VALUE self)
|
179
|
+
{
|
180
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
181
|
+
return rb_int_new(result->depth);
|
182
|
+
}
|
183
|
+
|
156
184
|
/* call-seq:
|
157
185
|
line_no -> int
|
158
186
|
|
@@ -160,7 +188,7 @@ prof_call_info_set_called(VALUE self, VALUE called)
|
|
160
188
|
static VALUE
|
161
189
|
prof_call_info_line(VALUE self)
|
162
190
|
{
|
163
|
-
prof_call_info_t *result =
|
191
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
164
192
|
return rb_int_new(result->line);
|
165
193
|
}
|
166
194
|
|
@@ -171,7 +199,7 @@ Returns the total amount of time spent in this method and its children. */
|
|
171
199
|
static VALUE
|
172
200
|
prof_call_info_total_time(VALUE self)
|
173
201
|
{
|
174
|
-
prof_call_info_t *result =
|
202
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
175
203
|
return rb_float_new(result->total_time);
|
176
204
|
}
|
177
205
|
|
@@ -182,8 +210,8 @@ adds total time time from call_info to self. */
|
|
182
210
|
static VALUE
|
183
211
|
prof_call_info_add_total_time(VALUE self, VALUE other)
|
184
212
|
{
|
185
|
-
prof_call_info_t *result =
|
186
|
-
prof_call_info_t *other_info =
|
213
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
214
|
+
prof_call_info_t *other_info = prof_get_call_info(other);
|
187
215
|
|
188
216
|
result->total_time += other_info->total_time;
|
189
217
|
return Qnil;
|
@@ -196,7 +224,7 @@ Returns the total amount of time spent in this method. */
|
|
196
224
|
static VALUE
|
197
225
|
prof_call_info_self_time(VALUE self)
|
198
226
|
{
|
199
|
-
prof_call_info_t *result =
|
227
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
200
228
|
|
201
229
|
return rb_float_new(result->self_time);
|
202
230
|
}
|
@@ -208,8 +236,8 @@ adds self time from call_info to self. */
|
|
208
236
|
static VALUE
|
209
237
|
prof_call_info_add_self_time(VALUE self, VALUE other)
|
210
238
|
{
|
211
|
-
prof_call_info_t *result =
|
212
|
-
prof_call_info_t *other_info =
|
239
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
240
|
+
prof_call_info_t *other_info = prof_get_call_info(other);
|
213
241
|
|
214
242
|
result->self_time += other_info->self_time;
|
215
243
|
return Qnil;
|
@@ -222,7 +250,7 @@ Returns the total amount of time this method waited for other threads. */
|
|
222
250
|
static VALUE
|
223
251
|
prof_call_info_wait_time(VALUE self)
|
224
252
|
{
|
225
|
-
prof_call_info_t *result =
|
253
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
226
254
|
|
227
255
|
return rb_float_new(result->wait_time);
|
228
256
|
}
|
@@ -235,8 +263,8 @@ adds wait time from call_info to self. */
|
|
235
263
|
static VALUE
|
236
264
|
prof_call_info_add_wait_time(VALUE self, VALUE other)
|
237
265
|
{
|
238
|
-
prof_call_info_t *result =
|
239
|
-
prof_call_info_t *other_info =
|
266
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
267
|
+
prof_call_info_t *other_info = prof_get_call_info(other);
|
240
268
|
|
241
269
|
result->wait_time += other_info->wait_time;
|
242
270
|
return Qnil;
|
@@ -249,7 +277,7 @@ Returns the call_infos parent call_info object (the method that called this meth
|
|
249
277
|
static VALUE
|
250
278
|
prof_call_info_parent(VALUE self)
|
251
279
|
{
|
252
|
-
prof_call_info_t *result =
|
280
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
253
281
|
if (result->parent)
|
254
282
|
return prof_call_info_wrap(result->parent);
|
255
283
|
else
|
@@ -263,11 +291,11 @@ Changes the parent of self to new_parent and returns it.*/
|
|
263
291
|
static VALUE
|
264
292
|
prof_call_info_set_parent(VALUE self, VALUE new_parent)
|
265
293
|
{
|
266
|
-
prof_call_info_t *result =
|
294
|
+
prof_call_info_t *result = prof_get_call_info(self);
|
267
295
|
if (new_parent == Qnil)
|
268
296
|
result->parent = NULL;
|
269
297
|
else
|
270
|
-
result->parent =
|
298
|
+
result->parent = prof_get_call_info(new_parent);
|
271
299
|
return prof_call_info_parent(self);
|
272
300
|
}
|
273
301
|
|
@@ -288,7 +316,7 @@ called (ie, children).*/
|
|
288
316
|
static VALUE
|
289
317
|
prof_call_info_children(VALUE self)
|
290
318
|
{
|
291
|
-
prof_call_info_t *call_info =
|
319
|
+
prof_call_info_t *call_info = prof_get_call_info(self);
|
292
320
|
if (call_info->children == Qnil)
|
293
321
|
{
|
294
322
|
call_info->children = rb_ary_new();
|
@@ -365,5 +393,6 @@ void rp_init_call_info()
|
|
365
393
|
rb_define_method(cCallInfo, "add_self_time", prof_call_info_add_self_time, 1);
|
366
394
|
rb_define_method(cCallInfo, "wait_time", prof_call_info_wait_time, 0);
|
367
395
|
rb_define_method(cCallInfo, "add_wait_time", prof_call_info_add_wait_time, 1);
|
396
|
+
rb_define_method(cCallInfo, "depth", prof_call_info_depth, 0);
|
368
397
|
rb_define_method(cCallInfo, "line", prof_call_info_line, 0);
|
369
398
|
}
|
@@ -1,112 +1,112 @@
|
|
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
|
-
static VALUE cMeasureCpuTime;
|
7
|
-
|
8
|
-
static unsigned long long cpu_frequency = 0;
|
9
|
-
|
10
|
-
/* The _WIN32 check is needed for msys (and maybe cygwin?) */
|
11
|
-
#if defined(__GNUC__) && !defined(_WIN32)
|
12
|
-
|
13
|
-
#include <stdint.h>
|
14
|
-
#include <time.h>
|
15
|
-
|
16
|
-
static unsigned long long get_cpu_time()
|
17
|
-
{
|
18
|
-
#if defined(__i386__) || defined(__x86_64__)
|
19
|
-
uint32_t a, d;
|
20
|
-
__asm__ volatile("rdtsc" : "=a" (a), "=d" (d));
|
21
|
-
return ((uint64_t)d << 32) + a;
|
22
|
-
#elif defined(__powerpc__) || defined(__ppc__)
|
23
|
-
unsigned long long x, y;
|
24
|
-
|
25
|
-
__asm__ __volatile__ ("\n\
|
26
|
-
1: mftbu %1\n\
|
27
|
-
mftb %L0\n\
|
28
|
-
mftbu %0\n\
|
29
|
-
cmpw %0,%1\n\
|
30
|
-
bne- 1b"
|
31
|
-
: "=r" (x), "=r" (y));
|
32
|
-
return x;
|
33
|
-
#endif
|
34
|
-
}
|
35
|
-
|
36
|
-
static unsigned long long get_cpu_frequency()
|
37
|
-
{
|
38
|
-
unsigned long long x, y;
|
39
|
-
|
40
|
-
struct timespec ts;
|
41
|
-
ts.tv_sec = 0;
|
42
|
-
ts.tv_nsec = 500000000;
|
43
|
-
x = get_cpu_time();
|
44
|
-
nanosleep(&ts, NULL);
|
45
|
-
y = get_cpu_time();
|
46
|
-
return (y - x) * 2;
|
47
|
-
}
|
48
|
-
|
49
|
-
#elif defined(_WIN32)
|
50
|
-
|
51
|
-
static unsigned long long get_cpu_time()
|
52
|
-
{
|
53
|
-
LARGE_INTEGER time;
|
54
|
-
QueryPerformanceCounter(&time);
|
55
|
-
return time.QuadPart;
|
56
|
-
};
|
57
|
-
|
58
|
-
static unsigned long long get_cpu_frequency()
|
59
|
-
{
|
60
|
-
LARGE_INTEGER cpu_frequency;
|
61
|
-
QueryPerformanceFrequency(&cpu_frequency);
|
62
|
-
return cpu_frequency.QuadPart;
|
63
|
-
};
|
64
|
-
#endif
|
65
|
-
|
66
|
-
static double
|
67
|
-
measure_cpu_time()
|
68
|
-
{
|
69
|
-
return ((double)get_cpu_time()) / cpu_frequency;
|
70
|
-
}
|
71
|
-
|
72
|
-
|
73
|
-
prof_measurer_t* prof_measurer_cpu_time()
|
74
|
-
{
|
75
|
-
prof_measurer_t* measure = ALLOC(prof_measurer_t);
|
76
|
-
measure->measure = measure_cpu_time;
|
77
|
-
return measure;
|
78
|
-
}
|
79
|
-
|
80
|
-
/* call-seq:
|
81
|
-
measure -> float
|
82
|
-
|
83
|
-
Returns the cpu time.*/
|
84
|
-
static VALUE
|
85
|
-
prof_measure_cpu_time(VALUE self)
|
86
|
-
{
|
87
|
-
return rb_float_new(measure_cpu_time());
|
88
|
-
}
|
89
|
-
|
90
|
-
/* call-seq:
|
91
|
-
cpu_frequency -> int
|
92
|
-
|
93
|
-
Returns the cpu's frequency. This value is needed when
|
94
|
-
RubyProf::measure_mode is set to CPU_TIME. */
|
95
|
-
static VALUE
|
96
|
-
prof_get_cpu_frequency(VALUE self)
|
97
|
-
{
|
98
|
-
return ULL2NUM(cpu_frequency);
|
99
|
-
}
|
100
|
-
|
101
|
-
void rp_init_measure_cpu_time()
|
102
|
-
{
|
103
|
-
rb_define_const(mProf, "CPU_TIME", INT2NUM(MEASURE_CPU_TIME));
|
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
|
+
static VALUE cMeasureCpuTime;
|
7
|
+
|
8
|
+
static unsigned long long cpu_frequency = 0;
|
9
|
+
|
10
|
+
/* The _WIN32 check is needed for msys (and maybe cygwin?) */
|
11
|
+
#if defined(__GNUC__) && !defined(_WIN32)
|
12
|
+
|
13
|
+
#include <stdint.h>
|
14
|
+
#include <time.h>
|
15
|
+
|
16
|
+
static unsigned long long get_cpu_time()
|
17
|
+
{
|
18
|
+
#if defined(__i386__) || defined(__x86_64__)
|
19
|
+
uint32_t a, d;
|
20
|
+
__asm__ volatile("rdtsc" : "=a" (a), "=d" (d));
|
21
|
+
return ((uint64_t)d << 32) + a;
|
22
|
+
#elif defined(__powerpc__) || defined(__ppc__)
|
23
|
+
unsigned long long x, y;
|
24
|
+
|
25
|
+
__asm__ __volatile__ ("\n\
|
26
|
+
1: mftbu %1\n\
|
27
|
+
mftb %L0\n\
|
28
|
+
mftbu %0\n\
|
29
|
+
cmpw %0,%1\n\
|
30
|
+
bne- 1b"
|
31
|
+
: "=r" (x), "=r" (y));
|
32
|
+
return x;
|
33
|
+
#endif
|
34
|
+
}
|
35
|
+
|
36
|
+
static unsigned long long get_cpu_frequency()
|
37
|
+
{
|
38
|
+
unsigned long long x, y;
|
39
|
+
|
40
|
+
struct timespec ts;
|
41
|
+
ts.tv_sec = 0;
|
42
|
+
ts.tv_nsec = 500000000;
|
43
|
+
x = get_cpu_time();
|
44
|
+
nanosleep(&ts, NULL);
|
45
|
+
y = get_cpu_time();
|
46
|
+
return (y - x) * 2;
|
47
|
+
}
|
48
|
+
|
49
|
+
#elif defined(_WIN32)
|
50
|
+
|
51
|
+
static unsigned long long get_cpu_time()
|
52
|
+
{
|
53
|
+
LARGE_INTEGER time;
|
54
|
+
QueryPerformanceCounter(&time);
|
55
|
+
return time.QuadPart;
|
56
|
+
};
|
57
|
+
|
58
|
+
static unsigned long long get_cpu_frequency()
|
59
|
+
{
|
60
|
+
LARGE_INTEGER cpu_frequency;
|
61
|
+
QueryPerformanceFrequency(&cpu_frequency);
|
62
|
+
return cpu_frequency.QuadPart;
|
63
|
+
};
|
64
|
+
#endif
|
65
|
+
|
66
|
+
static double
|
67
|
+
measure_cpu_time()
|
68
|
+
{
|
69
|
+
return ((double)get_cpu_time()) / cpu_frequency;
|
70
|
+
}
|
71
|
+
|
72
|
+
|
73
|
+
prof_measurer_t* prof_measurer_cpu_time()
|
74
|
+
{
|
75
|
+
prof_measurer_t* measure = ALLOC(prof_measurer_t);
|
76
|
+
measure->measure = measure_cpu_time;
|
77
|
+
return measure;
|
78
|
+
}
|
79
|
+
|
80
|
+
/* call-seq:
|
81
|
+
measure -> float
|
82
|
+
|
83
|
+
Returns the cpu time.*/
|
84
|
+
static VALUE
|
85
|
+
prof_measure_cpu_time(VALUE self)
|
86
|
+
{
|
87
|
+
return rb_float_new(measure_cpu_time());
|
88
|
+
}
|
89
|
+
|
90
|
+
/* call-seq:
|
91
|
+
cpu_frequency -> int
|
92
|
+
|
93
|
+
Returns the cpu's frequency. This value is needed when
|
94
|
+
RubyProf::measure_mode is set to CPU_TIME. */
|
95
|
+
static VALUE
|
96
|
+
prof_get_cpu_frequency(VALUE self)
|
97
|
+
{
|
98
|
+
return ULL2NUM(cpu_frequency);
|
99
|
+
}
|
100
|
+
|
101
|
+
void rp_init_measure_cpu_time()
|
102
|
+
{
|
103
|
+
rb_define_const(mProf, "CPU_TIME", INT2NUM(MEASURE_CPU_TIME));
|
104
104
|
rb_define_const(mProf, "CPU_TIME_ENABLED", Qtrue);
|
105
|
-
|
106
|
-
cMeasureCpuTime = rb_define_class_under(mMeasure, "CpuTime", rb_cObject);
|
107
|
-
rb_define_singleton_method(cMeasureCpuTime, "measure", prof_measure_cpu_time, 0);
|
108
|
-
rb_define_singleton_method(cMeasureCpuTime, "frequency", prof_get_cpu_frequency, 0);
|
109
|
-
|
110
|
-
/* Get cpu_frequency */
|
111
|
-
cpu_frequency = get_cpu_frequency();
|
112
|
-
}
|
105
|
+
|
106
|
+
cMeasureCpuTime = rb_define_class_under(mMeasure, "CpuTime", rb_cObject);
|
107
|
+
rb_define_singleton_method(cMeasureCpuTime, "measure", prof_measure_cpu_time, 0);
|
108
|
+
rb_define_singleton_method(cMeasureCpuTime, "frequency", prof_get_cpu_frequency, 0);
|
109
|
+
|
110
|
+
/* Get cpu_frequency */
|
111
|
+
cpu_frequency = get_cpu_frequency();
|
112
|
+
}
|