ruby-prof 0.11.0.rc1 → 0.11.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- 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/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 +64 -85
- 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 +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
|
+
}
|