ruby-prof 0.7.10 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +5 -0
- data/Rakefile +2 -2
- data/bin/go.rb +2 -0
- data/ext/ruby_prof.c +77 -65
- data/ext/version.h +3 -3
- data/lib/ruby-prof.rb +1 -0
- data/lib/ruby-prof/flat_printer.rb +1 -2
- data/lib/ruby-prof/flat_printer_with_line_numbers.rb +16 -7
- data/test/basic_test.rb +5 -5
- data/test/prime.rb +1 -1
- data/test/printers_test.rb +55 -11
- data/test/recursive_test.rb +4 -4
- data/test/stack_test.rb +1 -1
- data/test/thread_test.rb +22 -9
- metadata +3 -2
data/CHANGES
CHANGED
data/Rakefile
CHANGED
@@ -123,7 +123,7 @@ end
|
|
123
123
|
|
124
124
|
require 'fileutils'
|
125
125
|
|
126
|
-
desc 'Build
|
126
|
+
desc 'Build ruby_prof.so'
|
127
127
|
task :build do
|
128
128
|
build(false)
|
129
129
|
end
|
@@ -144,7 +144,7 @@ def build(with_debug)
|
|
144
144
|
end
|
145
145
|
|
146
146
|
desc 'build ruby_prof.so with verbose symbols enabled'
|
147
|
-
task :
|
147
|
+
task :build_debug do
|
148
148
|
build(true)
|
149
149
|
end
|
150
150
|
|
data/bin/go.rb
ADDED
data/ext/ruby_prof.c
CHANGED
@@ -884,9 +884,6 @@ get_event_name(rb_event_flag_t event)
|
|
884
884
|
}
|
885
885
|
#endif
|
886
886
|
|
887
|
-
|
888
|
-
// these differ 1.9/1.8
|
889
|
-
|
890
887
|
static prof_method_t*
|
891
888
|
#ifdef RUBY_VM
|
892
889
|
get_method(rb_event_flag_t event, VALUE klass, ID mid, int depth, st_table* method_table)
|
@@ -924,7 +921,6 @@ update_result(prof_measure_t total_time,
|
|
924
921
|
prof_frame_t *frame)
|
925
922
|
{
|
926
923
|
prof_measure_t self_time = total_time - frame->child_time - frame->wait_time;
|
927
|
-
|
928
924
|
prof_call_info_t *call_info = frame->call_info;
|
929
925
|
|
930
926
|
/* Update information about the current method */
|
@@ -941,15 +937,15 @@ update_result(prof_measure_t total_time,
|
|
941
937
|
static thread_data_t *
|
942
938
|
switch_thread(VALUE thread_id, prof_measure_t now)
|
943
939
|
{
|
944
|
-
|
945
|
-
|
940
|
+
prof_frame_t *frame = NULL;
|
941
|
+
prof_measure_t wait_time = 0;
|
946
942
|
/* Get new thread information. */
|
947
943
|
thread_data_t *thread_data = threads_table_lookup(threads_tbl, thread_id);
|
948
944
|
|
949
945
|
/* How long has this thread been waiting? */
|
950
946
|
wait_time = now - thread_data->last_switch;
|
951
947
|
|
952
|
-
thread_data->last_switch = 0
|
948
|
+
thread_data->last_switch = now; // XXXX a test that fails if this is 0
|
953
949
|
|
954
950
|
/* Get the frame at the top of the stack. This may represent
|
955
951
|
the current method (EVENT_LINE, EVENT_RETURN) or the
|
@@ -959,8 +955,6 @@ switch_thread(VALUE thread_id, prof_measure_t now)
|
|
959
955
|
if (frame) {
|
960
956
|
frame->wait_time += wait_time;
|
961
957
|
}
|
962
|
-
|
963
|
-
|
964
958
|
|
965
959
|
/* Save on the last thread the time of the context switch
|
966
960
|
and reset this thread's last context switch to 0.*/
|
@@ -995,7 +989,7 @@ pop_frame(thread_data_t *thread_data, prof_measure_t now)
|
|
995
989
|
parent_frame = stack_peek(thread_data->stack);
|
996
990
|
if (parent_frame)
|
997
991
|
{
|
998
|
-
|
992
|
+
parent_frame->child_time += total_time;
|
999
993
|
}
|
1000
994
|
|
1001
995
|
update_result(total_time, parent_frame, frame); // only time it's called
|
@@ -1024,18 +1018,19 @@ pop_frames(st_data_t key, st_data_t value, st_data_t now_arg)
|
|
1024
1018
|
static void
|
1025
1019
|
prof_pop_threads()
|
1026
1020
|
{
|
1027
|
-
/* Get current measurement*/
|
1021
|
+
/* Get current measurement */
|
1028
1022
|
prof_measure_t now = get_measurement();
|
1029
1023
|
st_foreach(threads_tbl, pop_frames, (st_data_t) &now);
|
1030
1024
|
}
|
1031
1025
|
|
1032
1026
|
|
1033
1027
|
#ifdef RUBY_VM
|
1028
|
+
|
1029
|
+
/* These are mostly to avoid bugs in core */
|
1030
|
+
static inline void walk_up_until_right_frame(prof_frame_t *frame, thread_data_t* thread_data, ID mid, VALUE klass, prof_measure_t now);
|
1034
1031
|
void prof_install_hook();
|
1035
1032
|
void prof_remove_hook();
|
1036
|
-
#endif
|
1037
1033
|
|
1038
|
-
#ifdef RUBY_VM
|
1039
1034
|
static void
|
1040
1035
|
prof_event_hook(rb_event_flag_t event, VALUE data, VALUE self, ID mid, VALUE klass)
|
1041
1036
|
#else
|
@@ -1049,15 +1044,15 @@ prof_event_hook(rb_event_flag_t event, NODE *node, VALUE self, ID mid, VALUE kla
|
|
1049
1044
|
thread_data_t* thread_data = NULL;
|
1050
1045
|
prof_frame_t *frame = NULL;
|
1051
1046
|
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
if (event != RUBY_EVENT_C_CALL && event != RUBY_EVENT_C_RETURN) {
|
1056
|
-
// guess these are already set for C call in 1.9?
|
1047
|
+
#ifdef RUBY_VM
|
1048
|
+
if (event != RUBY_EVENT_C_CALL && event != RUBY_EVENT_C_RETURN) {
|
1049
|
+
// guess these are already set for C calls in 1.9, then?
|
1057
1050
|
rb_frame_method_id_and_class(&mid, &klass);
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1051
|
+
}
|
1052
|
+
#endif
|
1053
|
+
|
1054
|
+
/* Get current timestamp */
|
1055
|
+
now = get_measurement();
|
1061
1056
|
|
1062
1057
|
#ifdef DEBUG
|
1063
1058
|
/* This code is here for debug purposes - uncomment it out
|
@@ -1068,9 +1063,9 @@ prof_event_hook(rb_event_flag_t event, NODE *node, VALUE self, ID mid, VALUE kla
|
|
1068
1063
|
|
1069
1064
|
VALUE thread = rb_thread_current();
|
1070
1065
|
VALUE thread_id = rb_obj_id(thread);
|
1071
|
-
char* class_name = NULL;
|
1072
|
-
char* method_name = rb_id2name(mid);
|
1073
|
-
char* source_file = rb_sourcefile();
|
1066
|
+
const char* class_name = NULL;
|
1067
|
+
const char* method_name = rb_id2name(mid);
|
1068
|
+
const char* source_file = rb_sourcefile();
|
1074
1069
|
unsigned int source_line = rb_sourceline();
|
1075
1070
|
|
1076
1071
|
char* event_name = get_event_name(event);
|
@@ -1083,9 +1078,9 @@ prof_event_hook(rb_event_flag_t event, NODE *node, VALUE self, ID mid, VALUE kla
|
|
1083
1078
|
if (last_thread_id != thread_id) {
|
1084
1079
|
printf("\n");
|
1085
1080
|
}
|
1086
|
-
|
1087
|
-
printf("%2u
|
1088
|
-
thread_id, event_name, source_file, source_line, class_name, method_name);
|
1081
|
+
|
1082
|
+
printf("%2u:%2ums %-8s %s:%2d %s#%s\n",
|
1083
|
+
(unsigned int) thread_id, (unsigned int) now, event_name, source_file, source_line, class_name, method_name);
|
1089
1084
|
fflush(stdout);
|
1090
1085
|
last_thread_id = thread_id;
|
1091
1086
|
}
|
@@ -1096,18 +1091,15 @@ prof_event_hook(rb_event_flag_t event, NODE *node, VALUE self, ID mid, VALUE kla
|
|
1096
1091
|
the results but aren't important to them results. */
|
1097
1092
|
if (self == mProf) return;
|
1098
1093
|
|
1099
|
-
/* Get current measurement*/
|
1100
|
-
now = get_measurement();
|
1101
|
-
|
1102
1094
|
/* Get the current thread information. */
|
1103
1095
|
thread = rb_thread_current();
|
1104
1096
|
thread_id = rb_obj_id(thread);
|
1105
1097
|
|
1106
|
-
#ifdef RUBY_VM
|
1107
|
-
|
1108
|
-
|
1109
|
-
|
1110
|
-
#endif
|
1098
|
+
# ifdef RUBY_VM
|
1099
|
+
/* ensure that new threads are hooked [sigh] (bug in core) */
|
1100
|
+
prof_remove_hook();
|
1101
|
+
prof_install_hook();
|
1102
|
+
# endif
|
1111
1103
|
|
1112
1104
|
if (exclude_threads_tbl &&
|
1113
1105
|
st_lookup(exclude_threads_tbl, (st_data_t) thread_id, 0))
|
@@ -1115,24 +1107,34 @@ prof_event_hook(rb_event_flag_t event, NODE *node, VALUE self, ID mid, VALUE kla
|
|
1115
1107
|
return;
|
1116
1108
|
}
|
1117
1109
|
|
1110
|
+
|
1118
1111
|
/* Was there a context switch? */
|
1119
1112
|
if (!last_thread_data || last_thread_data->thread_id != thread_id)
|
1120
1113
|
thread_data = switch_thread(thread_id, now);
|
1121
1114
|
else
|
1122
1115
|
thread_data = last_thread_data;
|
1123
1116
|
|
1124
|
-
|
1125
|
-
frame = stack_peek(thread_data->stack);
|
1126
|
-
|
1117
|
+
|
1127
1118
|
switch (event) {
|
1128
1119
|
case RUBY_EVENT_LINE:
|
1129
1120
|
{
|
1130
1121
|
/* Keep track of the current line number in this method. When
|
1131
1122
|
a new method is called, we know what line number it was
|
1132
1123
|
called from. */
|
1124
|
+
|
1125
|
+
/* Get the current frame for the current thread. */
|
1126
|
+
frame = stack_peek(thread_data->stack);
|
1127
|
+
|
1133
1128
|
if (frame)
|
1134
1129
|
{
|
1135
|
-
frame->line = rb_sourceline();
|
1130
|
+
frame->line = rb_sourceline();
|
1131
|
+
|
1132
|
+
# ifdef RUBY_VM
|
1133
|
+
// disabled till I figure out why it causes
|
1134
|
+
// us to lose valuable frame information...maybe mid comes in wrong sometimes?
|
1135
|
+
// walk_up_until_right_frame(frame, thread_data, mid, klass, now);
|
1136
|
+
# endif
|
1137
|
+
|
1136
1138
|
break;
|
1137
1139
|
}
|
1138
1140
|
|
@@ -1143,6 +1145,8 @@ prof_event_hook(rb_event_flag_t event, NODE *node, VALUE self, ID mid, VALUE kla
|
|
1143
1145
|
case RUBY_EVENT_CALL:
|
1144
1146
|
case RUBY_EVENT_C_CALL:
|
1145
1147
|
{
|
1148
|
+
/* Get the current frame for the current thread. */
|
1149
|
+
frame = stack_peek(thread_data->stack);
|
1146
1150
|
prof_call_info_t *call_info = NULL;
|
1147
1151
|
prof_method_t *method = NULL;
|
1148
1152
|
|
@@ -1154,20 +1158,20 @@ prof_event_hook(rb_event_flag_t event, NODE *node, VALUE self, ID mid, VALUE kla
|
|
1154
1158
|
klass = (BUILTIN_TYPE(klass) == T_ICLASS ? RBASIC(klass)->klass : klass);
|
1155
1159
|
|
1156
1160
|
/* Assume this is the first time we have called this method. */
|
1157
|
-
#ifdef RUBY_VM
|
1158
|
-
|
1159
|
-
#else
|
1160
|
-
|
1161
|
-
#endif
|
1161
|
+
#ifdef RUBY_VM
|
1162
|
+
method = get_method(event, klass, mid, 0, thread_data->method_table);
|
1163
|
+
#else
|
1164
|
+
method = get_method(event, node, klass, mid, 0, thread_data->method_table);
|
1165
|
+
#endif
|
1162
1166
|
/* Check for a recursive call */
|
1163
|
-
while (method->active) // it's while because we start at 0 and then
|
1167
|
+
while (method->active) // it's while because we start at 0 and then inc. to the right recursive depth
|
1164
1168
|
{
|
1165
1169
|
/* Yes, this method is already active somewhere up the stack */
|
1166
|
-
#ifdef RUBY_VM
|
1167
|
-
|
1168
|
-
#else
|
1169
|
-
|
1170
|
-
#endif
|
1170
|
+
#ifdef RUBY_VM
|
1171
|
+
method = get_method(event, klass, mid, method->key->depth + 1, thread_data->method_table);
|
1172
|
+
#else
|
1173
|
+
method = get_method(event, node, klass, mid, method->key->depth + 1, thread_data->method_table);
|
1174
|
+
#endif
|
1171
1175
|
}
|
1172
1176
|
method->active = 1;
|
1173
1177
|
|
@@ -1195,27 +1199,35 @@ prof_event_hook(rb_event_flag_t event, NODE *node, VALUE self, ID mid, VALUE kla
|
|
1195
1199
|
frame->wait_time = 0;
|
1196
1200
|
frame->child_time = 0;
|
1197
1201
|
frame->line = rb_sourceline();
|
1198
|
-
|
1199
1202
|
break;
|
1200
1203
|
}
|
1201
1204
|
case RUBY_EVENT_RETURN:
|
1202
1205
|
case RUBY_EVENT_C_RETURN:
|
1203
|
-
{
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1206
|
+
{
|
1207
|
+
frame = pop_frame(thread_data, now);
|
1208
|
+
|
1209
|
+
# ifdef RUBY_VM
|
1210
|
+
// we need to walk up the stack to find the right one [http://redmine.ruby-lang.org/issues/show/2610] (for now)
|
1211
|
+
// sometimes frames don't have line and source somehow [like blank]
|
1212
|
+
// if we hit one there's not much we can do...I guess...
|
1213
|
+
// or maybe we don't have one because we're at the top or something.
|
1214
|
+
walk_up_until_right_frame(frame, thread_data, mid, klass, now);
|
1215
|
+
# endif
|
1216
|
+
|
1217
|
+
break;
|
1218
|
+
}
|
1216
1219
|
}
|
1217
1220
|
}
|
1218
1221
|
|
1222
|
+
#ifdef RUBY_VM
|
1223
|
+
|
1224
|
+
static inline void walk_up_until_right_frame(prof_frame_t *frame, thread_data_t* thread_data, ID mid, VALUE klass, prof_measure_t now) {
|
1225
|
+
// while it doesn't match, pop on up until we have found where we belong...
|
1226
|
+
while( frame && frame->call_info->target->key->mid && frame->call_info->target->key->klass && ((frame->call_info->target->key->mid != mid) || (frame->call_info->target->key->klass != klass))){
|
1227
|
+
frame = pop_frame(thread_data, now);
|
1228
|
+
}
|
1229
|
+
}
|
1230
|
+
#endif
|
1219
1231
|
|
1220
1232
|
/* ======== ProfResult ============== */
|
1221
1233
|
|
@@ -1429,7 +1441,7 @@ prof_install_hook()
|
|
1429
1441
|
rb_add_event_hook(prof_event_hook,
|
1430
1442
|
RUBY_EVENT_CALL | RUBY_EVENT_RETURN |
|
1431
1443
|
RUBY_EVENT_C_CALL | RUBY_EVENT_C_RETURN
|
1432
|
-
| RUBY_EVENT_LINE, Qnil); //
|
1444
|
+
| RUBY_EVENT_LINE, Qnil); // RUBY_EVENT_SWITCH
|
1433
1445
|
#else
|
1434
1446
|
rb_add_event_hook(prof_event_hook,
|
1435
1447
|
RUBY_EVENT_CALL | RUBY_EVENT_RETURN |
|
data/ext/version.h
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#define RUBY_PROF_VERSION "0.
|
1
|
+
#define RUBY_PROF_VERSION "0.8.1"
|
2
2
|
#define RUBY_PROF_VERSION_MAJ 0
|
3
|
-
#define RUBY_PROF_VERSION_MIN
|
4
|
-
#define RUBY_PROF_VERSION_MIC
|
3
|
+
#define RUBY_PROF_VERSION_MIN 8
|
4
|
+
#define RUBY_PROF_VERSION_MIC 1
|
data/lib/ruby-prof.rb
CHANGED
@@ -9,6 +9,7 @@ require "ruby-prof/graph_printer"
|
|
9
9
|
require "ruby-prof/graph_html_printer"
|
10
10
|
require "ruby-prof/call_tree_printer"
|
11
11
|
require "ruby-prof/symbol_to_proc" # for 1.8's benefit
|
12
|
+
#require "ruby-prof/result"
|
12
13
|
|
13
14
|
module RubyProf
|
14
15
|
# See if the user specified the clock mode via
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'ruby-prof/abstract_printer'
|
2
|
-
|
2
|
+
require 'pathname'
|
3
3
|
module RubyProf
|
4
4
|
# Generates flat[link:files/examples/flat_txt.html] profile reports as text.
|
5
5
|
# To use the flat printer with line numbers:
|
@@ -31,7 +31,6 @@ module RubyProf
|
|
31
31
|
@output << "Total: %0.6f\n" % total_time
|
32
32
|
@output << "\n"
|
33
33
|
@output << " %self total self wait child calls name\n"
|
34
|
-
|
35
34
|
sum = 0
|
36
35
|
methods.each do |method|
|
37
36
|
self_percent = (method.self_time / total_time) * 100
|
@@ -48,14 +47,24 @@ module RubyProf
|
|
48
47
|
method.wait_time, # wait
|
49
48
|
method.children_time, # children
|
50
49
|
method.called, # calls
|
51
|
-
method_name(method), # name
|
52
|
-
method.source_file, # filename
|
53
|
-
method.line # line in said file
|
50
|
+
method_name(method), # name
|
54
51
|
]
|
55
52
|
if method.source_file != 'ruby_runtime'
|
56
|
-
@output << " %s:%s" % [method.source_file, method.line]
|
53
|
+
@output << " %s:%s" % [File.expand_path(method.source_file), method.line]
|
57
54
|
end
|
58
|
-
@output << "\n"
|
55
|
+
@output << "\n\tcalled from: "
|
56
|
+
|
57
|
+
# make sure they're unique
|
58
|
+
method.call_infos.map{|ci|
|
59
|
+
if ci.parent && ci.parent.target.source_file != 'ruby_runtime'
|
60
|
+
[method_name(ci.parent.target), File.expand_path(ci.parent.target.source_file), ci.parent.target.line]
|
61
|
+
else
|
62
|
+
nil
|
63
|
+
end
|
64
|
+
}.compact.uniq.each{|args|
|
65
|
+
@output << " %s (%s:%s) " % args
|
66
|
+
}
|
67
|
+
@output << "\n\n"
|
59
68
|
end
|
60
69
|
end
|
61
70
|
end
|
data/test/basic_test.rb
CHANGED
@@ -148,15 +148,15 @@ class BasicTest < Test::Unit::TestCase
|
|
148
148
|
|
149
149
|
# Check times
|
150
150
|
assert_in_delta(0.2, methods[0].total_time, 0.02)
|
151
|
-
assert_in_delta(0, methods[0].wait_time, 0.
|
152
|
-
assert_in_delta(0, methods[0].self_time, 0.
|
151
|
+
assert_in_delta(0, methods[0].wait_time, 0.02)
|
152
|
+
assert_in_delta(0, methods[0].self_time, 0.02)
|
153
153
|
|
154
154
|
assert_in_delta(0.2, methods[1].total_time, 0.02)
|
155
|
-
assert_in_delta(0, methods[1].wait_time, 0.
|
156
|
-
assert_in_delta(0, methods[1].self_time, 0.
|
155
|
+
assert_in_delta(0, methods[1].wait_time, 0.02)
|
156
|
+
assert_in_delta(0, methods[1].self_time, 0.02)
|
157
157
|
|
158
158
|
assert_in_delta(0.2, methods[2].total_time, 0.02)
|
159
|
-
assert_in_delta(0, methods[2].wait_time, 0.
|
159
|
+
assert_in_delta(0, methods[2].wait_time, 0.02)
|
160
160
|
assert_in_delta(0.2, methods[2].self_time, 0.02)
|
161
161
|
|
162
162
|
assert_in_delta(0, methods[3].total_time, 0.01)
|
data/test/prime.rb
CHANGED
data/test/printers_test.rb
CHANGED
@@ -1,15 +1,22 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'test/unit'
|
3
3
|
require 'ruby-prof'
|
4
|
-
require '
|
4
|
+
require File.dirname(__FILE__) + '/prime'
|
5
5
|
|
6
6
|
# -- Tests ----
|
7
7
|
class PrintersTest < Test::Unit::TestCase
|
8
|
+
|
9
|
+
def go
|
10
|
+
run_primes
|
11
|
+
end
|
12
|
+
|
8
13
|
def setup
|
9
|
-
RubyProf::measure_mode = RubyProf::
|
14
|
+
RubyProf::measure_mode = RubyProf::WALL_TIME # WALL_TIME so we can use sleep in our test
|
10
15
|
@result = RubyProf.profile do
|
11
16
|
run_primes
|
17
|
+
go
|
12
18
|
end
|
19
|
+
|
13
20
|
end
|
14
21
|
|
15
22
|
def test_printers
|
@@ -26,10 +33,8 @@ class PrintersTest < Test::Unit::TestCase
|
|
26
33
|
printer.print
|
27
34
|
|
28
35
|
printer = RubyProf::CallTreePrinter.new(@result)
|
29
|
-
printer.print(STDOUT)
|
30
|
-
|
31
|
-
# we should get here
|
32
|
-
assert(true)
|
36
|
+
printer.print(STDOUT)
|
37
|
+
# we should get here
|
33
38
|
end
|
34
39
|
|
35
40
|
def test_flat_string
|
@@ -41,7 +46,7 @@ class PrintersTest < Test::Unit::TestCase
|
|
41
46
|
output = ''
|
42
47
|
|
43
48
|
printer = klass.new(@result)
|
44
|
-
|
49
|
+
printer.print(output)
|
45
50
|
|
46
51
|
assert_match(/Thread ID: -?\d+/i, output)
|
47
52
|
assert_match(/Total: \d+\.\d+/i, output)
|
@@ -53,12 +58,22 @@ class PrintersTest < Test::Unit::TestCase
|
|
53
58
|
output = helper_test_flat_string RubyProf::FlatPrinterWithLineNumbers
|
54
59
|
assert_match(/prime.rb/, output)
|
55
60
|
assert_no_match(/ruby_runtime:0/, output)
|
61
|
+
assert_match(/called from/, output)
|
62
|
+
|
63
|
+
# should combine common parents
|
64
|
+
if RUBY_VERSION < '1.9'
|
65
|
+
assert_equal(3, output.scan(/Object#is_prime/).length)
|
66
|
+
else
|
67
|
+
# 1.9
|
68
|
+
assert_equal(2, output.scan(/Object#is_prime/).length)
|
69
|
+
end
|
70
|
+
assert_no_match(/\.\/test\/prime.rb/, output) # don't use relative paths
|
56
71
|
end
|
57
72
|
|
58
73
|
def test_graph_html_string
|
59
74
|
output = ''
|
60
75
|
printer = RubyProf::GraphHtmlPrinter.new(@result)
|
61
|
-
|
76
|
+
printer.print(output)
|
62
77
|
|
63
78
|
assert_match( /DTD HTML 4\.01/i, output )
|
64
79
|
assert_match( %r{<th>Total Time</th>}i, output )
|
@@ -68,7 +83,7 @@ class PrintersTest < Test::Unit::TestCase
|
|
68
83
|
def test_graph_string
|
69
84
|
output = ''
|
70
85
|
printer = RubyProf::GraphPrinter.new(@result)
|
71
|
-
|
86
|
+
printer.print(output)
|
72
87
|
|
73
88
|
assert_match( /Thread ID: -?\d+/i, output )
|
74
89
|
assert_match( /Total Time: \d+\.\d+/i, output )
|
@@ -78,9 +93,38 @@ class PrintersTest < Test::Unit::TestCase
|
|
78
93
|
def test_call_tree_string
|
79
94
|
output = ''
|
80
95
|
printer = RubyProf::CallTreePrinter.new(@result)
|
81
|
-
|
96
|
+
printer.print(output)
|
82
97
|
|
83
98
|
assert_match(/fn=Object::find_primes/i, output)
|
84
|
-
assert_match(/events:
|
99
|
+
assert_match(/events: wall_time/i, output)
|
100
|
+
end
|
101
|
+
|
102
|
+
def do_nothing
|
103
|
+
start = Time.now
|
104
|
+
while(Time.now == start)
|
105
|
+
end
|
85
106
|
end
|
107
|
+
|
108
|
+
def test_all_with_small_percentiles
|
109
|
+
|
110
|
+
result = RubyProf.profile do
|
111
|
+
sleep 2
|
112
|
+
do_nothing
|
113
|
+
end
|
114
|
+
|
115
|
+
# RubyProf::CallTreePrinter doesn't "do" a min_percent
|
116
|
+
# RubyProf::FlatPrinter only outputs if self time > percent...
|
117
|
+
# RubyProf::FlatPrinterWithLineNumbers same
|
118
|
+
for klass in [ RubyProf::GraphPrinter, RubyProf::GraphHtmlPrinter]
|
119
|
+
puts klass
|
120
|
+
printer = klass.new(result)
|
121
|
+
out = ''
|
122
|
+
output = printer.print(out, :min_percent => 0.00000001 )
|
123
|
+
assert_match(/do_nothing/, out)
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
|
86
130
|
end
|
data/test/recursive_test.rb
CHANGED
@@ -57,10 +57,10 @@ class RecursiveTest < Test::Unit::TestCase
|
|
57
57
|
method = methods[1]
|
58
58
|
assert_equal('Object#simple', method.full_name)
|
59
59
|
assert_equal(1, method.called)
|
60
|
-
assert_in_delta(2, method.total_time, 0.
|
61
|
-
assert_in_delta(0, method.self_time, 0.
|
62
|
-
assert_in_delta(0, method.wait_time, 0.
|
63
|
-
assert_in_delta(2, method.children_time, 0.
|
60
|
+
assert_in_delta(2, method.total_time, 0.02)
|
61
|
+
assert_in_delta(0, method.self_time, 0.02)
|
62
|
+
assert_in_delta(0, method.wait_time, 0.02)
|
63
|
+
assert_in_delta(2, method.children_time, 0.02)
|
64
64
|
|
65
65
|
assert_equal(1, method.call_infos.length)
|
66
66
|
call_info = method.call_infos[0]
|
data/test/stack_test.rb
CHANGED
@@ -67,7 +67,7 @@ class StackTest < Test::Unit::TestCase
|
|
67
67
|
method = methods[1]
|
68
68
|
assert_equal('StackClass#a', method.full_name)
|
69
69
|
assert_equal(1, method.called)
|
70
|
-
assert_in_delta(8, method.total_time, 0.
|
70
|
+
assert_in_delta(8, method.total_time, 0.15)
|
71
71
|
assert_in_delta(0, method.wait_time, 0.01)
|
72
72
|
assert_in_delta(0, method.self_time, 0.01)
|
73
73
|
assert_in_delta(8, method.children_time, 0.05)
|
data/test/thread_test.rb
CHANGED
@@ -45,8 +45,12 @@ class ThreadTest < Test::Unit::TestCase
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def test_thread_timings
|
48
|
-
|
48
|
+
RubyProf.start
|
49
49
|
thread = Thread.new do
|
50
|
+
sleep 0 # force it to hit thread.join, below, first
|
51
|
+
# thus forcing sleep(1), below, to be counted as (wall) self_time
|
52
|
+
# since we currently count time "in some other thread" as self.wait_time
|
53
|
+
# for whatever reason
|
50
54
|
sleep(1)
|
51
55
|
end
|
52
56
|
thread.join
|
@@ -71,10 +75,10 @@ class ThreadTest < Test::Unit::TestCase
|
|
71
75
|
|
72
76
|
method = methods[1]
|
73
77
|
assert_equal('Kernel#sleep', method.full_name)
|
74
|
-
assert_equal(
|
78
|
+
assert_equal(2, method.called)
|
75
79
|
assert_in_delta(1, method.total_time, 0.01)
|
76
|
-
assert_in_delta(0, method.self_time, 0.01)
|
77
|
-
assert_in_delta(
|
80
|
+
assert_in_delta(1.0, method.self_time, 0.01)
|
81
|
+
assert_in_delta(0, method.wait_time, 0.01)
|
78
82
|
assert_in_delta(0, method.children_time, 0.01)
|
79
83
|
|
80
84
|
assert_equal(1, method.call_infos.length)
|
@@ -91,7 +95,7 @@ class ThreadTest < Test::Unit::TestCase
|
|
91
95
|
assert_equal('ThreadTest#test_thread_timings', method.full_name)
|
92
96
|
# the sub calls to Object#new, when popped,
|
93
97
|
# cause the parent frame to be created for method #test_thread_timings, which means a +1 when it's popped in the end
|
94
|
-
# xxxx a test that shows it the other way, too
|
98
|
+
# xxxx a test that shows it the other way, too (never creates parent frame--if that's even possible)
|
95
99
|
assert_equal(1, method.called)
|
96
100
|
assert_in_delta(1, method.total_time, 0.01)
|
97
101
|
assert_in_delta(0, method.self_time, 0.05)
|
@@ -107,10 +111,8 @@ class ThreadTest < Test::Unit::TestCase
|
|
107
111
|
assert_equal('Thread#join', method.full_name)
|
108
112
|
assert_equal(1, method.called)
|
109
113
|
assert_in_delta(1, method.total_time, 0.01)
|
110
|
-
assert_in_delta(
|
111
|
-
|
112
|
-
# but for our purposes...I guess that's ok for now...sure.
|
113
|
-
assert_in_delta(0, method.wait_time, 0.01)
|
114
|
+
assert_in_delta(0, method.self_time, 0.01)
|
115
|
+
assert_in_delta(1.0, method.wait_time, 0.01)
|
114
116
|
assert_in_delta(0, method.children_time, 0.01)
|
115
117
|
|
116
118
|
assert_equal(1, method.call_infos.length)
|
@@ -145,6 +147,17 @@ class ThreadTest < Test::Unit::TestCase
|
|
145
147
|
assert_equal(0, call_info.children.length)
|
146
148
|
end
|
147
149
|
|
150
|
+
# useless test
|
151
|
+
def test_thread_back_and_forth
|
152
|
+
result = RubyProf.profile do
|
153
|
+
a = Thread.new { 100_000.times { sleep 0 }}
|
154
|
+
b = Thread.new { 100_000.times { sleep 0 }}
|
155
|
+
a.join
|
156
|
+
b.join
|
157
|
+
end
|
158
|
+
assert result.threads.values.flatten.sort[-1].total_time < 10 # 10s
|
159
|
+
end
|
160
|
+
|
148
161
|
def test_thread
|
149
162
|
result = RubyProf.profile do
|
150
163
|
begin
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-prof
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shugo Maeda, Charlie Savage, Roger Pack
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-
|
12
|
+
date: 2010-02-03 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -42,6 +42,7 @@ files:
|
|
42
42
|
- README
|
43
43
|
- LICENSE
|
44
44
|
- CHANGES
|
45
|
+
- bin/go.rb
|
45
46
|
- bin/ruby-prof
|
46
47
|
- examples/flat.txt
|
47
48
|
- examples/graph.html
|