ruby-prof 0.7.10 → 0.8.1
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 +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
|