ruby-prof 1.0.0

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 (97) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +523 -0
  3. data/LICENSE +25 -0
  4. data/README.rdoc +5 -0
  5. data/Rakefile +110 -0
  6. data/bin/ruby-prof +380 -0
  7. data/bin/ruby-prof-check-trace +45 -0
  8. data/ext/ruby_prof/extconf.rb +36 -0
  9. data/ext/ruby_prof/rp_allocation.c +292 -0
  10. data/ext/ruby_prof/rp_allocation.h +31 -0
  11. data/ext/ruby_prof/rp_call_info.c +283 -0
  12. data/ext/ruby_prof/rp_call_info.h +35 -0
  13. data/ext/ruby_prof/rp_measure_allocations.c +52 -0
  14. data/ext/ruby_prof/rp_measure_memory.c +42 -0
  15. data/ext/ruby_prof/rp_measure_process_time.c +63 -0
  16. data/ext/ruby_prof/rp_measure_wall_time.c +62 -0
  17. data/ext/ruby_prof/rp_measurement.c +236 -0
  18. data/ext/ruby_prof/rp_measurement.h +49 -0
  19. data/ext/ruby_prof/rp_method.c +642 -0
  20. data/ext/ruby_prof/rp_method.h +70 -0
  21. data/ext/ruby_prof/rp_profile.c +881 -0
  22. data/ext/ruby_prof/rp_profile.h +36 -0
  23. data/ext/ruby_prof/rp_stack.c +196 -0
  24. data/ext/ruby_prof/rp_stack.h +56 -0
  25. data/ext/ruby_prof/rp_thread.c +338 -0
  26. data/ext/ruby_prof/rp_thread.h +36 -0
  27. data/ext/ruby_prof/ruby_prof.c +48 -0
  28. data/ext/ruby_prof/ruby_prof.h +17 -0
  29. data/ext/ruby_prof/vc/ruby_prof.sln +31 -0
  30. data/ext/ruby_prof/vc/ruby_prof.vcxproj +143 -0
  31. data/lib/ruby-prof.rb +53 -0
  32. data/lib/ruby-prof/assets/call_stack_printer.css.html +117 -0
  33. data/lib/ruby-prof/assets/call_stack_printer.js.html +385 -0
  34. data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
  35. data/lib/ruby-prof/assets/graph_printer.html.erb +356 -0
  36. data/lib/ruby-prof/call_info.rb +57 -0
  37. data/lib/ruby-prof/call_info_visitor.rb +38 -0
  38. data/lib/ruby-prof/compatibility.rb +109 -0
  39. data/lib/ruby-prof/exclude_common_methods.rb +198 -0
  40. data/lib/ruby-prof/measurement.rb +14 -0
  41. data/lib/ruby-prof/method_info.rb +90 -0
  42. data/lib/ruby-prof/printers/abstract_printer.rb +118 -0
  43. data/lib/ruby-prof/printers/call_info_printer.rb +51 -0
  44. data/lib/ruby-prof/printers/call_stack_printer.rb +269 -0
  45. data/lib/ruby-prof/printers/call_tree_printer.rb +151 -0
  46. data/lib/ruby-prof/printers/dot_printer.rb +132 -0
  47. data/lib/ruby-prof/printers/flat_printer.rb +52 -0
  48. data/lib/ruby-prof/printers/graph_html_printer.rb +64 -0
  49. data/lib/ruby-prof/printers/graph_printer.rb +114 -0
  50. data/lib/ruby-prof/printers/multi_printer.rb +127 -0
  51. data/lib/ruby-prof/profile.rb +33 -0
  52. data/lib/ruby-prof/rack.rb +171 -0
  53. data/lib/ruby-prof/task.rb +147 -0
  54. data/lib/ruby-prof/thread.rb +35 -0
  55. data/lib/ruby-prof/version.rb +3 -0
  56. data/lib/unprof.rb +10 -0
  57. data/ruby-prof.gemspec +58 -0
  58. data/test/abstract_printer_test.rb +26 -0
  59. data/test/alias_test.rb +129 -0
  60. data/test/basic_test.rb +129 -0
  61. data/test/call_info_visitor_test.rb +31 -0
  62. data/test/duplicate_names_test.rb +32 -0
  63. data/test/dynamic_method_test.rb +53 -0
  64. data/test/enumerable_test.rb +21 -0
  65. data/test/exceptions_test.rb +24 -0
  66. data/test/exclude_methods_test.rb +146 -0
  67. data/test/exclude_threads_test.rb +53 -0
  68. data/test/line_number_test.rb +161 -0
  69. data/test/marshal_test.rb +119 -0
  70. data/test/measure_allocations.rb +30 -0
  71. data/test/measure_allocations_test.rb +385 -0
  72. data/test/measure_allocations_trace_test.rb +385 -0
  73. data/test/measure_memory_trace_test.rb +756 -0
  74. data/test/measure_process_time_test.rb +849 -0
  75. data/test/measure_times.rb +54 -0
  76. data/test/measure_wall_time_test.rb +459 -0
  77. data/test/multi_printer_test.rb +71 -0
  78. data/test/no_method_class_test.rb +15 -0
  79. data/test/parser_timings.rb +24 -0
  80. data/test/pause_resume_test.rb +166 -0
  81. data/test/prime.rb +56 -0
  82. data/test/printer_call_tree_test.rb +31 -0
  83. data/test/printer_flat_test.rb +68 -0
  84. data/test/printer_graph_html_test.rb +60 -0
  85. data/test/printer_graph_test.rb +41 -0
  86. data/test/printers_test.rb +141 -0
  87. data/test/printing_recursive_graph_test.rb +81 -0
  88. data/test/rack_test.rb +157 -0
  89. data/test/recursive_test.rb +210 -0
  90. data/test/singleton_test.rb +38 -0
  91. data/test/stack_printer_test.rb +64 -0
  92. data/test/start_stop_test.rb +109 -0
  93. data/test/test_helper.rb +24 -0
  94. data/test/thread_test.rb +144 -0
  95. data/test/unique_call_path_test.rb +190 -0
  96. data/test/yarv_test.rb +56 -0
  97. metadata +189 -0
@@ -0,0 +1,146 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+
6
+ module ExcludeMethodsModule
7
+ def c
8
+ 1.times { |i| ExcludeMethodsModule.d }
9
+ end
10
+
11
+ def self.d
12
+ 1.times { |i| ExcludeMethodsClass.e }
13
+ end
14
+ end
15
+
16
+ class ExcludeMethodsClass
17
+ include ExcludeMethodsModule
18
+
19
+ def a
20
+ 1.times { |i| b }
21
+ end
22
+
23
+ def b
24
+ 1.times { |i| c; self.class.e }
25
+ end
26
+
27
+ def self.e
28
+ 1.times { |i| f }
29
+ end
30
+
31
+ def self.f
32
+ sleep 0.1
33
+ end
34
+ end
35
+
36
+ class ExcludeMethodsTest < TestCase
37
+ def setup
38
+ # Need to use wall time for this test due to the sleep calls
39
+ RubyProf::measure_mode = RubyProf::WALL_TIME
40
+ end
41
+
42
+ def test_methods_can_be_profiled
43
+ obj = ExcludeMethodsClass.new
44
+ prf = RubyProf::Profile.new
45
+
46
+ result = prf.profile { 5.times {obj.a} }
47
+ methods = result.threads.first.methods.sort.reverse
48
+
49
+ assert_equal(10, methods.count)
50
+ assert_equal('ExcludeMethodsTest#test_methods_can_be_profiled', methods[0].full_name)
51
+ assert_equal('Integer#times', methods[1].full_name)
52
+ assert_equal('ExcludeMethodsClass#a', methods[2].full_name)
53
+ assert_equal('ExcludeMethodsClass#b', methods[3].full_name)
54
+ assert_equal('<Class::ExcludeMethodsClass>#e', methods[4].full_name)
55
+ assert_equal('<Class::ExcludeMethodsClass>#f', methods[5].full_name)
56
+ assert_equal('Kernel#sleep', methods[6].full_name)
57
+ assert_equal('ExcludeMethodsModule#c', methods[7].full_name)
58
+ assert_equal('<Module::ExcludeMethodsModule>#d', methods[8].full_name)
59
+ assert_equal('Kernel#class', methods[9].full_name)
60
+ end
61
+
62
+ def test_methods_can_be_hidden1
63
+ obj = ExcludeMethodsClass.new
64
+ prf = RubyProf::Profile.new
65
+
66
+ prf.exclude_methods!(Integer, :times)
67
+
68
+ result = prf.profile { 5.times {obj.a} }
69
+ methods = result.threads.first.methods.sort.reverse
70
+
71
+ assert_equal(9, methods.count)
72
+ assert_equal('ExcludeMethodsTest#test_methods_can_be_hidden1', methods[0].full_name)
73
+ assert_equal('ExcludeMethodsClass#a', methods[1].full_name)
74
+ assert_equal('ExcludeMethodsClass#b', methods[2].full_name)
75
+ assert_equal('<Class::ExcludeMethodsClass>#e', methods[3].full_name)
76
+ assert_equal('<Class::ExcludeMethodsClass>#f', methods[4].full_name)
77
+ assert_equal('Kernel#sleep', methods[5].full_name)
78
+ assert_equal('ExcludeMethodsModule#c', methods[6].full_name)
79
+ assert_equal('<Module::ExcludeMethodsModule>#d', methods[7].full_name)
80
+ assert_equal('Kernel#class', methods[8].full_name)
81
+ end
82
+
83
+ def test_methods_can_be_hidden2
84
+ obj = ExcludeMethodsClass.new
85
+ prf = RubyProf::Profile.new
86
+
87
+ prf.exclude_methods!(Integer, :times)
88
+ prf.exclude_methods!(ExcludeMethodsClass.singleton_class, :f)
89
+ prf.exclude_methods!(ExcludeMethodsModule.singleton_class, :d)
90
+
91
+ result = prf.profile { 5.times {obj.a} }
92
+ methods = result.threads.first.methods.sort.reverse
93
+
94
+ assert_equal(7, methods.count)
95
+ assert_equal('ExcludeMethodsTest#test_methods_can_be_hidden2', methods[0].full_name)
96
+ assert_equal('ExcludeMethodsClass#a', methods[1].full_name)
97
+ assert_equal('ExcludeMethodsClass#b', methods[2].full_name)
98
+ assert_equal('<Class::ExcludeMethodsClass>#e', methods[3].full_name)
99
+ assert_equal('Kernel#sleep', methods[4].full_name)
100
+ assert_equal('ExcludeMethodsModule#c', methods[5].full_name)
101
+ assert_equal('Kernel#class', methods[6].full_name)
102
+ end
103
+
104
+ def test_exclude_common_methods1
105
+ obj = ExcludeMethodsClass.new
106
+ prf = RubyProf::Profile.new
107
+
108
+ prf.exclude_common_methods!
109
+
110
+ result = prf.profile { 5.times {obj.a} }
111
+ methods = result.threads.first.methods.sort.reverse
112
+
113
+ assert_equal(9, methods.count)
114
+ assert_equal('ExcludeMethodsTest#test_exclude_common_methods1', methods[0].full_name)
115
+ assert_equal('ExcludeMethodsClass#a', methods[1].full_name)
116
+ assert_equal('ExcludeMethodsClass#b', methods[2].full_name)
117
+ end
118
+
119
+ def test_exclude_common_methods2
120
+ obj = ExcludeMethodsClass.new
121
+
122
+ result = RubyProf.profile(exclude_common: true) { 5.times {obj.a} }
123
+ methods = result.threads.first.methods.sort.reverse
124
+
125
+ assert_equal(9, methods.count)
126
+ assert_equal('ExcludeMethodsTest#test_exclude_common_methods2', methods[0].full_name)
127
+ assert_equal('ExcludeMethodsClass#a', methods[1].full_name)
128
+ assert_equal('ExcludeMethodsClass#b', methods[2].full_name)
129
+ end
130
+
131
+ private
132
+
133
+ def assert_method_has_been_eliminated(result, eliminated_method)
134
+ result.threads.each do |thread|
135
+ thread.methods.each do |method|
136
+ method.call_infos.each do |ci|
137
+ assert(ci.target != eliminated_method, "broken self")
138
+ assert(ci.parent.target != eliminated_method, "broken parent") if ci.parent
139
+ ci.children.each do |callee|
140
+ assert(callee.target != eliminated_method, "broken kid")
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+
6
+
7
+ # -- Tests ----
8
+ class ExcludeThreadsTest < TestCase
9
+ def test_exclude_threads
10
+
11
+ def thread1_proc
12
+ sleep(0.5)
13
+ sleep(2)
14
+ end
15
+
16
+ def thread2_proc
17
+ sleep(0.5)
18
+ sleep(2)
19
+ end
20
+
21
+ thread1 = Thread.new do
22
+ thread1_proc
23
+ end
24
+
25
+ thread2 = Thread.new do
26
+ thread2_proc
27
+ end
28
+
29
+ # exclude_threads already includes the minitest thread pool
30
+ RubyProf.exclude_threads += [ thread2 ]
31
+
32
+ RubyProf.start
33
+
34
+ thread1.join
35
+ thread2.join
36
+
37
+ result = RubyProf.stop
38
+
39
+ assert_equal(2, result.threads.length)
40
+
41
+ output = Array.new
42
+ result.threads.each do |thread|
43
+ thread.methods.each do | m |
44
+ if m.full_name.index("ExcludeThreadsTest#thread") == 0
45
+ output.push(m.full_name)
46
+ end
47
+ end
48
+ end
49
+
50
+ assert_equal(1, output.length)
51
+ assert_equal("ExcludeThreadsTest#thread1_proc", output[0])
52
+ end
53
+ end
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path('../test_helper', __FILE__)
5
+
6
+ class LineNumbers
7
+ def method_1
8
+ method_2
9
+ filler = 1
10
+ method_3
11
+ end
12
+
13
+ def method_2
14
+ filler = 1
15
+ 2.times do |i|
16
+ filler = 2
17
+ method_3
18
+ end
19
+ end
20
+
21
+ def method_3
22
+ sleep(0.4)
23
+ method_4
24
+ end
25
+
26
+ def method_4
27
+ sleep(1)
28
+ end
29
+ end
30
+
31
+ # -- Tests ----
32
+ class LineNumbersTest < TestCase
33
+ def test_function_line_no
34
+ numbers = LineNumbers.new
35
+
36
+ result = RubyProf.profile do
37
+ numbers.method_1
38
+ end
39
+
40
+ methods = result.threads.first.methods.sort.reverse
41
+ assert_equal(7, methods.length)
42
+
43
+ # Method 0
44
+ method = methods[0]
45
+ assert_equal('LineNumbersTest#test_function_line_no', method.full_name)
46
+ assert_equal(37, method.line)
47
+
48
+ assert_equal(1, method.callers.count)
49
+ call_info = method.callers[0]
50
+ assert_nil(call_info.parent)
51
+ assert_equal(37, call_info.line)
52
+
53
+ assert_equal(1, method.callees.count)
54
+ call_info = method.callees[0]
55
+ assert_equal('LineNumbers#method_1', call_info.target.full_name)
56
+ assert_equal(37, call_info.line)
57
+
58
+ # Method 1
59
+ method = methods[1]
60
+ assert_equal('LineNumbers#method_1', method.full_name)
61
+ assert_equal(7, method.line)
62
+
63
+ assert_equal(1, method.callers.count)
64
+ call_info = method.callers[0]
65
+ assert_equal('LineNumbersTest#test_function_line_no', call_info.parent.full_name)
66
+ assert_equal(37, call_info.line)
67
+
68
+ assert_equal(2, method.callees.count)
69
+ call_info = method.callees[0]
70
+ assert_equal('LineNumbers#method_2', call_info.target.full_name)
71
+ assert_equal(8, call_info.line)
72
+
73
+ call_info = method.callees[1]
74
+ assert_equal('LineNumbers#method_3', call_info.target.full_name)
75
+ assert_equal(10, call_info.line)
76
+
77
+ # Method 2
78
+ method = methods[2]
79
+ assert_equal('LineNumbers#method_3', method.full_name)
80
+ assert_equal(21, method.line)
81
+
82
+ assert_equal(2, method.callers.count)
83
+ call_info = method.callers[0]
84
+ assert_equal('Integer#times', call_info.parent.full_name)
85
+ assert_equal(17, call_info.line)
86
+
87
+ call_info = method.callers[1]
88
+ assert_equal('LineNumbers#method_1', call_info.parent.full_name)
89
+ assert_equal(10, call_info.line)
90
+
91
+ assert_equal(2, method.callees.count)
92
+ call_info = method.callees[0]
93
+ assert_equal('Kernel#sleep', call_info.target.full_name)
94
+ assert_equal(22, call_info.line)
95
+
96
+ call_info = method.callees[1]
97
+ assert_equal('LineNumbers#method_4', call_info.target.full_name)
98
+ assert_equal(23, call_info.line)
99
+
100
+ # Method 3
101
+ method = methods[3]
102
+ assert_equal('Kernel#sleep', method.full_name)
103
+ assert_equal(0, method.line)
104
+
105
+ assert_equal(2, method.callers.count)
106
+ call_info = method.callers[0]
107
+ assert_equal('LineNumbers#method_3', call_info.parent.full_name)
108
+ assert_equal(22, call_info.line)
109
+
110
+ call_info = method.callers[1]
111
+ assert_equal('LineNumbers#method_4', call_info.parent.full_name)
112
+ assert_equal(27, call_info.line)
113
+
114
+ assert_equal(0, method.callees.count)
115
+
116
+ # Method 4
117
+ method = methods[4]
118
+ assert_equal('LineNumbers#method_4', method.full_name)
119
+ assert_equal(26, method.line)
120
+
121
+ assert_equal(1, method.callers.count)
122
+ call_info = method.callers[0]
123
+ assert_equal('LineNumbers#method_3', call_info.parent.full_name)
124
+ assert_equal(23, call_info.line)
125
+
126
+ assert_equal(1, method.callees.count)
127
+ call_info = method.callees[0]
128
+ assert_equal('Kernel#sleep', call_info.target.full_name)
129
+ assert_equal(27, call_info.line)
130
+
131
+ # Method 5
132
+ method = methods[5]
133
+ assert_equal('LineNumbers#method_2', method.full_name)
134
+ assert_equal(13, method.line)
135
+
136
+ assert_equal(1, method.callers.count)
137
+ call_info = method.callers[0]
138
+ assert_equal('LineNumbers#method_1', call_info.parent.full_name)
139
+ assert_equal(8, call_info.line)
140
+
141
+ assert_equal(1, method.callees.count)
142
+ call_info = method.callees[0]
143
+ assert_equal('Integer#times', call_info.target.full_name)
144
+ assert_equal(15, call_info.line)
145
+
146
+ # Method 6
147
+ method = methods[6]
148
+ assert_equal('Integer#times', method.full_name)
149
+ assert_equal(0, method.line)
150
+
151
+ assert_equal(1, method.callers.count)
152
+ call_info = method.callers[0]
153
+ assert_equal('LineNumbers#method_2', call_info.parent.full_name)
154
+ assert_equal(15, call_info.line)
155
+
156
+ assert_equal(1, method.callees.count)
157
+ call_info = method.callees[0]
158
+ assert_equal('LineNumbers#method_3', call_info.target.full_name)
159
+ assert_equal(17, call_info.line)
160
+ end
161
+ end
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ require File.expand_path("../test_helper", __FILE__)
5
+ require 'stringio'
6
+
7
+ class MarshalTest < TestCase
8
+ def verify_profile(profile_1, profile_2)
9
+ verify_threads(profile_1.threads, profile_2.threads)
10
+ end
11
+
12
+ def verify_threads(threads_1, threads_2)
13
+ assert_equal(threads_1.count, threads_2.count)
14
+ threads_1.count.times do |i|
15
+ thread_1 = threads_1[i]
16
+ thread_2 = threads_2[i]
17
+ assert_nil(thread_2.id)
18
+ assert_equal(thread_1.fiber_id, thread_2.fiber_id)
19
+
20
+ verify_methods(thread_1.methods, thread_2.methods)
21
+ end
22
+ end
23
+
24
+ def verify_methods(methods_1, methods_2)
25
+ assert_equal(methods_1.count, methods_2.count)
26
+
27
+ methods_1.count.times do |i|
28
+ method_1 = methods_1[i]
29
+ method_2 = methods_2[i]
30
+
31
+ assert_equal(method_1.klass_name, method_2.klass_name)
32
+ assert_equal(method_1.klass_flags, method_2.klass_flags)
33
+
34
+ assert_equal(method_1.method_name, method_2.method_name)
35
+ assert_equal(method_1.full_name, method_2.full_name)
36
+
37
+ assert_equal(method_1.recursive?, method_2.recursive?)
38
+ assert_equal(method_1.root?, method_2.root?)
39
+ assert_equal(method_1.excluded?, method_2.excluded?)
40
+
41
+ assert_equal(method_1.source_file, method_2.source_file)
42
+ assert_equal(method_1.line, method_2.line)
43
+
44
+ verify_measurement(method_1.measurement, method_2.measurement)
45
+
46
+ verify_call_infos(method_1.callers, method_2.callers)
47
+ verify_call_infos(method_1.callees, method_2.callees)
48
+
49
+ verify_allocations(method_1.allocations, method_2.allocations)
50
+ end
51
+ end
52
+
53
+ def verify_allocations(allocations_1, allocations_2)
54
+ assert_equal(allocations_1.count, allocations_2.count)
55
+
56
+ allocations_1.count.times do |i|
57
+ allocation_1 = allocations_1[i]
58
+ allocation_2 = allocations_2[i]
59
+
60
+ assert_equal(allocation_1.klass_name, allocation_2.klass_name)
61
+ assert_equal(allocation_1.klass_flags, allocation_2.klass_flags)
62
+
63
+ assert_equal(allocation_1.count, allocation_2.count)
64
+ assert_equal(allocation_1.memory, allocation_2.memory)
65
+
66
+ assert_equal(allocation_1.source_file, allocation_2.source_file)
67
+ assert_equal(allocation_1.line, allocation_2.line)
68
+ end
69
+ end
70
+
71
+ def verify_call_infos(call_infos_1, call_infos_2)
72
+ assert_equal(call_infos_1.count, call_infos_2.count)
73
+ call_infos_1.count.times do |i|
74
+ call_info_1 = call_infos_1[i]
75
+ call_info_2 = call_infos_2[i]
76
+ verify_call_info(call_info_1, call_info_2)
77
+ end
78
+ end
79
+
80
+ def verify_call_info(call_info_1, call_info_2)
81
+ assert_equal(call_info_1.parent, call_info_2.parent)
82
+ assert_equal(call_info_1.target, call_info_2.target)
83
+
84
+ assert_equal(call_info_1.depth, call_info_2.depth)
85
+ assert_equal(call_info_1.source_file, call_info_2.source_file)
86
+ assert_equal(call_info_1.line, call_info_2.line)
87
+
88
+ verify_measurement(call_info_1.measurement, call_info_2.measurement)
89
+ end
90
+
91
+ def verify_measurement(measurement_1, measurement_2)
92
+ assert_equal(measurement_1.total_time, measurement_2.total_time)
93
+ assert_equal(measurement_1.self_time, measurement_2.self_time)
94
+ assert_equal(measurement_1.wait_time, measurement_2.wait_time)
95
+ assert_equal(measurement_1.called, measurement_2.called)
96
+ end
97
+
98
+ def test_marshal
99
+ profile_1 = RubyProf.profile do
100
+ 1.times { RubyProf::C1.new.sleep_wait }
101
+ end
102
+
103
+ data = Marshal.dump(profile_1)
104
+ profile_2 = Marshal.load(data)
105
+
106
+ verify_profile(profile_1, profile_2)
107
+ end
108
+
109
+ def test_singleton
110
+ profile_1 = RubyProf.profile do
111
+ SingletonTest.instance.busy_wait
112
+ end
113
+
114
+ data = Marshal.dump(profile_1)
115
+ profile_2 = Marshal.load(data)
116
+
117
+ verify_profile(profile_1, profile_2)
118
+ end
119
+ end