jeremy-ruby-prof 0.6.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.
Files changed (47) hide show
  1. data/CHANGES +158 -0
  2. data/LICENSE +23 -0
  3. data/README +416 -0
  4. data/Rakefile +141 -0
  5. data/bin/ruby-prof +196 -0
  6. data/examples/flat.txt +55 -0
  7. data/examples/graph.html +823 -0
  8. data/examples/graph.txt +170 -0
  9. data/ext/extconf.rb +24 -0
  10. data/ext/measure_allocations.h +58 -0
  11. data/ext/measure_cpu_time.h +149 -0
  12. data/ext/measure_memory.h +104 -0
  13. data/ext/measure_process_time.h +52 -0
  14. data/ext/measure_wall_time.h +53 -0
  15. data/ext/ruby_prof.c +1680 -0
  16. data/lib/ruby-prof.rb +45 -0
  17. data/lib/ruby-prof/abstract_printer.rb +42 -0
  18. data/lib/ruby-prof/call_tree_printer.rb +76 -0
  19. data/lib/ruby-prof/flat_printer.rb +76 -0
  20. data/lib/ruby-prof/graph_html_printer.rb +255 -0
  21. data/lib/ruby-prof/graph_printer.rb +163 -0
  22. data/lib/ruby-prof/profile_test.rb +147 -0
  23. data/lib/ruby-prof/task.rb +147 -0
  24. data/lib/unprof.rb +8 -0
  25. data/test/basic_test.rb +190 -0
  26. data/test/duplicate_names_test.rb +33 -0
  27. data/test/exceptions_test.rb +19 -0
  28. data/test/line_number_test.rb +69 -0
  29. data/test/measure_mode_test.rb +91 -0
  30. data/test/measurement_test.rb +61 -0
  31. data/test/module_test.rb +57 -0
  32. data/test/no_method_class_test.rb +14 -0
  33. data/test/prime.rb +60 -0
  34. data/test/prime1.rb +17 -0
  35. data/test/prime2.rb +26 -0
  36. data/test/prime3.rb +17 -0
  37. data/test/prime_test.rb +24 -0
  38. data/test/printers_test.rb +74 -0
  39. data/test/profile_unit_test.rb +24 -0
  40. data/test/recursive_test.rb +144 -0
  41. data/test/singleton_test.rb +38 -0
  42. data/test/start_test.rb +24 -0
  43. data/test/test_helper.rb +55 -0
  44. data/test/test_suite.rb +20 -0
  45. data/test/thread_test.rb +135 -0
  46. data/test/timing_test.rb +133 -0
  47. metadata +112 -0
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+ require 'ruby-prof'
5
+ require 'test_helper'
6
+
7
+ # Need to use wall time for this test due to the sleep calls
8
+ RubyProf::measure_mode = RubyProf::WALL_TIME
9
+
10
+ module Foo
11
+ def Foo::hello
12
+ sleep(0.5)
13
+ end
14
+ end
15
+
16
+ module Bar
17
+ def Bar::hello
18
+ sleep(0.5)
19
+ Foo::hello
20
+ end
21
+
22
+ def hello
23
+ sleep(0.5)
24
+ Bar::hello
25
+ end
26
+ end
27
+
28
+ include Bar
29
+
30
+ class ModuleTest < Test::Unit::TestCase
31
+ def test_nested_modules
32
+ result = RubyProf.profile do
33
+ hello
34
+ end
35
+
36
+ methods = result.threads.values.first
37
+ methods = methods.sort.reverse
38
+
39
+ # Length should be 4
40
+ assert_equal(5, methods.length)
41
+
42
+ method = methods[0]
43
+ assert_equal('ModuleTest#test_nested_modules', method.full_name)
44
+
45
+ method = methods[1]
46
+ assert_equal('Kernel#sleep', method.full_name)
47
+
48
+ method = methods[2]
49
+ assert_equal('Bar#hello', method.full_name)
50
+
51
+ method = methods[3]
52
+ assert_equal('<Module::Bar>#hello', method.full_name)
53
+
54
+ method = methods[4]
55
+ assert_equal('<Module::Foo>#hello', method.full_name)
56
+ end
57
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'ruby-prof'
4
+
5
+ # Make sure this works with no class or method
6
+ result = RubyProf.profile do
7
+ sleep 1
8
+ end
9
+
10
+ method = result.threads.values.first.sort.last
11
+
12
+ if method.full_name != 'Global#[No method]'
13
+ raise(RuntimeError, "Wrong method name. Expected: Global#[No method]. Actual: #{method.full_name}")
14
+ end
@@ -0,0 +1,60 @@
1
+ # A silly little test program that finds prime numbers. It
2
+ # is intentionally badly designed to show off the use
3
+ # or ruby-prof.
4
+ #
5
+ # Source from http://people.cs.uchicago.edu/~bomb154/154/maclabs/profilers-lab/
6
+
7
+ def make_random_array(length, maxnum)
8
+ result = Array.new(length)
9
+ result.each_index do |i|
10
+ result[i] = rand(maxnum)
11
+ end
12
+
13
+ result
14
+ end
15
+
16
+ def is_prime(x)
17
+ y = 2
18
+ y.upto(x-1) do |i|
19
+ return false if (x % i) == 0
20
+ end
21
+ true
22
+ end
23
+
24
+ def find_primes(arr)
25
+ result = arr.select do |value|
26
+ is_prime(value)
27
+ end
28
+ result
29
+ end
30
+
31
+ def find_largest(primes)
32
+ largest = primes.first
33
+
34
+ # Intentionally use upto for example purposes
35
+ # (upto is also called from is_prime)
36
+ 0.upto(primes.length-1) do |i|
37
+ sleep(0.02)
38
+ prime = primes[i]
39
+ if prime > largest
40
+ largest = prime
41
+ end
42
+ end
43
+ largest
44
+ end
45
+
46
+ def run_primes
47
+ length = 500
48
+ maxnum = 10000
49
+
50
+ # Create random numbers
51
+ random_array = make_random_array(length, maxnum)
52
+
53
+ # Find the primes
54
+ primes = find_primes(random_array)
55
+
56
+ # Find the largest primes
57
+ largest = find_largest(primes)
58
+ end
59
+
60
+ run_primes
@@ -0,0 +1,17 @@
1
+ require 'prime2'
2
+ require 'prime3'
3
+
4
+ def run_primes
5
+ length = 500
6
+ maxnum = 10000
7
+
8
+ # Create random numbers
9
+ random_array = make_random_array(length, maxnum)
10
+
11
+ # Find the primes
12
+ primes = find_primes(random_array)
13
+
14
+ # Find the largest primes
15
+ largest = find_largest(primes)
16
+ #puts "largest is #{largest}"
17
+ end
@@ -0,0 +1,26 @@
1
+ require 'prime3'
2
+
3
+ # Need to use wall time for this test due to the sleep calls
4
+ RubyProf::measure_mode = RubyProf::WALL_TIME
5
+
6
+ def find_primes(arr)
7
+ result = arr.select do |value|
8
+ is_prime(value)
9
+ end
10
+ result
11
+ end
12
+
13
+ def find_largest(primes)
14
+ largest = primes.first
15
+
16
+ # Intentionally use upto for example purposes
17
+ # (upto is also called from is_prime)
18
+ 0.upto(primes.length-1) do |i|
19
+ sleep(0.02)
20
+ prime = primes[i]
21
+ if prime > largest
22
+ largest = prime
23
+ end
24
+ end
25
+ largest
26
+ end
@@ -0,0 +1,17 @@
1
+
2
+ def make_random_array(length, maxnum)
3
+ result = Array.new(length)
4
+ result.each_index do |i|
5
+ result[i] = rand(maxnum)
6
+ end
7
+
8
+ result
9
+ end
10
+
11
+ def is_prime(x)
12
+ y = 2
13
+ y.upto(x-1) do |i|
14
+ return false if (x % i) == 0
15
+ end
16
+ true
17
+ end
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+ require 'ruby-prof'
5
+ require 'prime'
6
+ require 'test_helper'
7
+
8
+
9
+ # -- Tests ----
10
+ class PrimeTest < Test::Unit::TestCase
11
+ def test_consistency
12
+ result = RubyProf.profile do
13
+ run_primes
14
+ end
15
+
16
+ result.threads.values.each do |methods|
17
+ methods.each do |method|
18
+ check_parent_times(method)
19
+ check_parent_calls(method)
20
+ check_child_times(method)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env ruby
2
+ require 'test/unit'
3
+ require 'ruby-prof'
4
+ require 'prime'
5
+ require 'test_helper'
6
+
7
+
8
+ # -- Tests ----
9
+ class PrintersTest < Test::Unit::TestCase
10
+
11
+ def setup
12
+ @result = RubyProf.profile do
13
+ run_primes
14
+ end
15
+ end
16
+
17
+ def test_printers
18
+ printer = RubyProf::FlatPrinter.new(@result)
19
+ printer.print(STDOUT)
20
+
21
+ printer = RubyProf::GraphHtmlPrinter.new(@result)
22
+ printer.print
23
+
24
+ printer = RubyProf::GraphPrinter.new(@result)
25
+ printer.print
26
+
27
+ printer = RubyProf::CallTreePrinter.new(@result)
28
+ printer.print(STDOUT)
29
+
30
+ # we should get here
31
+ assert(true)
32
+ end
33
+
34
+ def test_flatprinter_duckfriendliness
35
+ output = ''
36
+
37
+ printer = RubyProf::FlatPrinter.new(@result)
38
+ assert_nothing_raised { printer.print( output ) }
39
+
40
+ assert_match( /Thread ID: \d+/i, output )
41
+ assert_match( /Total: \d+\.\d+/i, output )
42
+ assert_match( /Object#run_primes/i, output )
43
+ end
44
+
45
+ def test_graphhtmlprinter_duckfriendliness
46
+ output = ''
47
+ printer = RubyProf::GraphHtmlPrinter.new(@result)
48
+ assert_nothing_raised { printer.print(output) }
49
+
50
+ assert_match( /DTD HTML 4\.01/i, output )
51
+ assert_match( %r{<th>Total Time</th>}i, output )
52
+ assert_match( /Object#run_primes/i, output )
53
+ end
54
+
55
+ def test_graphprinter_duckfriendliness
56
+ output = ''
57
+ printer = RubyProf::GraphPrinter.new(@result)
58
+ assert_nothing_raised { printer.print(output) }
59
+
60
+ assert_match( /Thread ID: \d+/i, output )
61
+ assert_match( /Total Time: \d+\.\d+/i, output )
62
+ assert_match( /Object#run_primes/i, output )
63
+ end
64
+
65
+ def test_calltreeprinter_duckfriendliness
66
+ output = ''
67
+ printer = RubyProf::CallTreePrinter.new(@result)
68
+ assert_nothing_raised { printer.print(output) }
69
+
70
+ assert_match(/fn=Object::find_primes/i, output)
71
+ assert_match(/events: process_time/i, output)
72
+ end
73
+
74
+ end
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+ require 'ruby-prof'
5
+ require 'test_helper'
6
+ require 'ruby-prof/profile_test_case'
7
+
8
+ # Need to use wall time for this test due to the sleep calls
9
+ RubyProf::measure_mode = RubyProf::WALL_TIME
10
+
11
+ # -- Tests ----
12
+ class ProfileTest < Test::Unit::TestCase
13
+ def test_profile
14
+ sleep(2)
15
+ end
16
+
17
+ def teardown
18
+ profile_dir = output_directory
19
+ assert(File.exists?(profile_dir))
20
+
21
+ file_path = File.join(profile_dir, 'test_profile_profile_test.html')
22
+ assert(File.exists?(file_path))
23
+ end
24
+ end
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'test/unit'
4
+ require 'ruby-prof'
5
+ require 'test_helper'
6
+
7
+ # Need to use wall time for this test due to the sleep calls
8
+ RubyProf::measure_mode = RubyProf::WALL_TIME
9
+
10
+ def simple(n)
11
+ sleep(1)
12
+ n -= 1
13
+ return if n == 0
14
+ simple(n)
15
+ end
16
+
17
+ def cycle(n)
18
+ sub_cycle(n)
19
+ end
20
+
21
+ def sub_cycle(n)
22
+ sleep(1)
23
+ n -= 1
24
+ return if n == 0
25
+ cycle(n)
26
+ end
27
+
28
+ def factorial(n)
29
+ if n < 2 then
30
+ n
31
+ else
32
+ n * factorial(n-1)
33
+ end
34
+ end
35
+
36
+
37
+ # -- Tests ----
38
+ class RecursiveTest < Test::Unit::TestCase
39
+ def test_recursive
40
+ result = RubyProf.profile do
41
+ simple(2)
42
+ end
43
+
44
+ result.threads.values.each do |methods|
45
+ methods.each do |method|
46
+ check_parent_times(method)
47
+ check_parent_calls(method)
48
+ check_child_times(method)
49
+ end
50
+ end
51
+
52
+
53
+ methods = result.threads.values.first.sort.reverse
54
+ assert_equal(6, methods.length)
55
+
56
+ method = methods[0]
57
+ assert_equal('RecursiveTest#test_recursive', method.full_name)
58
+ assert_in_delta(2, method.total_time, 0.02)
59
+ assert_in_delta(0, method.self_time, 0.02)
60
+ assert_in_delta(0, method.wait_time, 0.02)
61
+ assert_in_delta(2, method.children_time, 0.02)
62
+ assert_equal(0, method.called)
63
+ assert_equal(0, method.parents.length)
64
+ assert_equal(1, method.children.length)
65
+
66
+ method = methods[1]
67
+ assert_equal('Object#simple', method.full_name)
68
+ assert_in_delta(2, method.total_time, 0.02)
69
+ assert_in_delta(0, method.self_time, 0.02)
70
+ assert_in_delta(0, method.wait_time, 0.02)
71
+ assert_in_delta(2, method.children_time, 0.02)
72
+ assert_equal(1, method.called)
73
+ assert_equal(1, method.parents.length)
74
+ assert_equal(4, method.children.length)
75
+
76
+ method = methods[2]
77
+ assert_equal('Kernel#sleep', method.full_name)
78
+ assert_in_delta(2, method.total_time, 0.02)
79
+ assert_in_delta(2, method.self_time, 0.02)
80
+ assert_in_delta(0, method.wait_time, 0.02)
81
+ assert_in_delta(0, method.children_time, 0.02)
82
+ assert_equal(2, method.called)
83
+ assert_equal(2, method.parents.length)
84
+ assert_equal(0, method.children.length)
85
+
86
+ method = methods[3]
87
+ assert_equal('Object#simple-1', method.full_name)
88
+ assert_in_delta(1, method.total_time, 0.02)
89
+ assert_in_delta(0, method.self_time, 0.02)
90
+ assert_in_delta(0, method.wait_time, 0.02)
91
+ assert_in_delta(1, method.children_time, 0.02)
92
+ assert_equal(1, method.called)
93
+ assert_equal(1, method.parents.length)
94
+ assert_equal(3, method.children.length)
95
+
96
+ method = methods[4]
97
+ assert_equal('Fixnum#==', method.full_name)
98
+ assert_in_delta(0, method.total_time, 0.02)
99
+ assert_in_delta(0, method.self_time, 0.02)
100
+ assert_in_delta(0, method.wait_time, 0.02)
101
+ assert_in_delta(0, method.children_time, 0.02)
102
+ assert_equal(2, method.called)
103
+ assert_equal(2, method.parents.length)
104
+ assert_equal(0, method.children.length)
105
+
106
+ method = methods[5]
107
+ assert_equal('Fixnum#-', method.full_name)
108
+ assert_in_delta(0, method.total_time, 0.02)
109
+ assert_in_delta(0, method.self_time, 0.02)
110
+ assert_in_delta(0, method.wait_time, 0.02)
111
+ assert_in_delta(0, method.children_time, 0.02)
112
+ assert_equal(2, method.called)
113
+ assert_equal(2, method.parents.length)
114
+ assert_equal(0, method.children.length)
115
+ end
116
+
117
+ def test_cycle
118
+ result = RubyProf.profile do
119
+ cycle(2)
120
+ end
121
+ result.threads.values.each do |methods|
122
+ methods.each do |method|
123
+ check_parent_times(method)
124
+ check_parent_calls(method)
125
+ check_child_times(method)
126
+ end
127
+ end
128
+ end
129
+
130
+ def test_factorial
131
+ result = RubyProf.profile do
132
+ # Around 700 on windows causes "stack level too deep" error
133
+ factorial(650)
134
+ end
135
+
136
+ result.threads.values.each do |methods|
137
+ methods.each do |method|
138
+ check_parent_times(method)
139
+ check_parent_calls(method)
140
+ check_child_times(method)
141
+ end
142
+ end
143
+ end
144
+ end