ruby-prof 0.13.1 → 0.14.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 (85) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +14 -0
  3. data/README.rdoc +1 -1
  4. data/Rakefile +2 -3
  5. data/bin/ruby-prof +4 -4
  6. data/bin/ruby-prof-check-trace +45 -0
  7. data/doc/LICENSE.html +49 -88
  8. data/doc/README_rdoc.html +92 -106
  9. data/doc/Rack.html +47 -116
  10. data/doc/Rack/RubyProf.html +119 -174
  11. data/doc/RubyProf.html +184 -216
  12. data/doc/RubyProf/AbstractPrinter.html +131 -162
  13. data/doc/RubyProf/AggregateCallInfo.html +136 -166
  14. data/doc/RubyProf/CallInfo.html +113 -154
  15. data/doc/RubyProf/CallInfoPrinter.html +56 -123
  16. data/doc/RubyProf/CallInfoVisitor.html +87 -216
  17. data/doc/RubyProf/CallStackPrinter.html +222 -215
  18. data/doc/RubyProf/CallTreePrinter.html +91 -142
  19. data/doc/RubyProf/Cmd.html +115 -157
  20. data/doc/RubyProf/DotPrinter.html +88 -140
  21. data/doc/RubyProf/FlatPrinter.html +66 -129
  22. data/doc/RubyProf/FlatPrinterWithLineNumbers.html +69 -132
  23. data/doc/RubyProf/GraphHtmlPrinter.html +115 -166
  24. data/doc/RubyProf/GraphPrinter.html +58 -125
  25. data/doc/RubyProf/MethodInfo.html +147 -172
  26. data/doc/RubyProf/MultiPrinter.html +104 -150
  27. data/doc/RubyProf/Profile.html +125 -179
  28. data/doc/RubyProf/ProfileTask.html +117 -157
  29. data/doc/RubyProf/Test.html +115 -154
  30. data/doc/RubyProf/Thread.html +87 -147
  31. data/doc/created.rid +13 -14
  32. data/doc/examples/flat_txt.html +51 -90
  33. data/doc/examples/graph_html.html +852 -0
  34. data/doc/examples/graph_txt.html +64 -92
  35. data/doc/fonts.css +167 -0
  36. data/doc/fonts/Lato-Light.ttf +0 -0
  37. data/doc/fonts/Lato-LightItalic.ttf +0 -0
  38. data/doc/fonts/Lato-Regular.ttf +0 -0
  39. data/doc/fonts/Lato-RegularItalic.ttf +0 -0
  40. data/doc/fonts/SourceCodePro-Bold.ttf +0 -0
  41. data/doc/fonts/SourceCodePro-Regular.ttf +0 -0
  42. data/doc/images/add.png +0 -0
  43. data/doc/images/arrow_up.png +0 -0
  44. data/doc/images/delete.png +0 -0
  45. data/doc/images/tag_blue.png +0 -0
  46. data/doc/index.html +75 -65
  47. data/doc/js/darkfish.js +0 -15
  48. data/doc/js/search.js +20 -5
  49. data/doc/js/search_index.js +1 -1
  50. data/doc/rdoc.css +255 -218
  51. data/doc/table_of_contents.html +751 -353
  52. data/ext/ruby_prof/extconf.rb +20 -22
  53. data/ext/ruby_prof/rp_measure_allocations.c +9 -5
  54. data/ext/ruby_prof/rp_measure_gc_runs.c +8 -0
  55. data/ext/ruby_prof/rp_measure_gc_time.c +5 -2
  56. data/ext/ruby_prof/rp_measure_wall_time.c +1 -0
  57. data/ext/ruby_prof/rp_method.c +0 -9
  58. data/ext/ruby_prof/rp_method.h +1 -6
  59. data/ext/ruby_prof/ruby_prof.c +32 -112
  60. data/ext/ruby_prof/ruby_prof.h +9 -10
  61. data/lib/ruby-prof.rb +2 -1
  62. data/lib/ruby-prof/aggregate_call_info.rb +4 -6
  63. data/lib/ruby-prof/call_info_visitor.rb +42 -44
  64. data/lib/ruby-prof/printers/graph_html_printer.rb +0 -8
  65. data/lib/ruby-prof/profile.rb +4 -4
  66. data/lib/ruby-prof/rack.rb +47 -47
  67. data/lib/ruby-prof/task.rb +0 -0
  68. data/lib/ruby-prof/thread.rb +22 -22
  69. data/lib/ruby-prof/version.rb +3 -0
  70. data/ruby-prof.gemspec +7 -11
  71. data/test/call_info_test.rb +78 -78
  72. data/test/call_info_visitor_test.rb +31 -31
  73. data/test/fiber_test.rb +2 -2
  74. data/test/measure_gc_runs_test.rb +1 -1
  75. data/test/measure_process_time_test.rb +7 -6
  76. data/test/printers_test.rb +4 -8
  77. data/test/recursive_test.rb +5 -9
  78. data/test/test_helper.rb +1 -1
  79. data/test/unique_call_path_test.rb +7 -29
  80. data/test/yarv_test.rb +55 -0
  81. metadata +63 -55
  82. data/ext/ruby_prof/version.h +0 -7
  83. data/lib/ruby-prof/test.rb +0 -150
  84. data/test/exec_test.rb +0 -14
  85. data/test/test_suite.rb +0 -37
@@ -2,173 +2,107 @@
2
2
 
3
3
  <html>
4
4
  <head>
5
- <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
5
+ <meta charset="UTF-8">
6
6
 
7
7
  <title>class RubyProf::MultiPrinter - ruby-prof</title>
8
8
 
9
- <link type="text/css" media="screen" href="../rdoc.css" rel="stylesheet">
9
+ <link href="../fonts.css" rel="stylesheet">
10
+ <link href="../rdoc.css" rel="stylesheet">
10
11
 
11
12
  <script type="text/javascript">
12
13
  var rdoc_rel_prefix = "../";
13
14
  </script>
14
15
 
15
- <script type="text/javascript" charset="utf-8" src="../js/jquery.js"></script>
16
- <script type="text/javascript" charset="utf-8" src="../js/navigation.js"></script>
17
- <script type="text/javascript" charset="utf-8" src="../js/search_index.js"></script>
18
- <script type="text/javascript" charset="utf-8" src="../js/search.js"></script>
19
- <script type="text/javascript" charset="utf-8" src="../js/searcher.js"></script>
20
- <script type="text/javascript" charset="utf-8" src="../js/darkfish.js"></script>
16
+ <script src="../js/jquery.js"></script>
17
+ <script src="../js/navigation.js"></script>
18
+ <script src="../js/search_index.js"></script>
19
+ <script src="../js/search.js"></script>
20
+ <script src="../js/searcher.js"></script>
21
+ <script src="../js/darkfish.js"></script>
21
22
 
22
23
 
23
- <body id="top" class="class">
24
- <nav id="metadata">
25
- <nav id="home-section" class="section">
26
- <h3 class="section-header">
27
- <a href="../index.html">Home</a>
24
+ <body id="top" role="document" class="class">
25
+ <nav role="navigation">
26
+ <div id="project-navigation">
27
+ <div id="home-section" role="region" title="Quick navigation" class="nav-section">
28
+ <h2>
29
+ <a href="../index.html" rel="home">Home</a>
30
+ </h2>
31
+
32
+ <div id="table-of-contents-navigation">
33
+ <a href="../table_of_contents.html#pages">Pages</a>
28
34
  <a href="../table_of_contents.html#classes">Classes</a>
29
35
  <a href="../table_of_contents.html#methods">Methods</a>
30
- </h3>
31
- </nav>
32
-
36
+ </div>
37
+ </div>
33
38
 
34
- <nav id="search-section" class="section project-section" class="initially-hidden">
39
+ <div id="search-section" role="search" class="project-section initially-hidden">
35
40
  <form action="#" method="get" accept-charset="utf-8">
36
- <h3 class="section-header">
37
- <input type="text" name="search" placeholder="Search" id="search-field"
41
+ <div id="search-field-wrapper">
42
+ <input id="search-field" role="combobox" aria-label="Search"
43
+ aria-autocomplete="list" aria-controls="search-results"
44
+ type="text" name="search" placeholder="Search" spellcheck="false"
38
45
  title="Type to search, Up and Down to navigate, Enter to load">
39
- </h3>
40
- </form>
46
+ </div>
41
47
 
42
- <ul id="search-results" class="initially-hidden"></ul>
43
- </nav>
44
-
45
-
46
- <div id="file-metadata">
47
- <nav id="file-list-section" class="section">
48
- <h3 class="section-header">Defined In</h3>
49
- <ul>
50
- <li>lib/ruby-prof/printers/multi_printer.rb
51
- </ul>
52
- </nav>
48
+ <ul id="search-results" aria-label="Search Results"
49
+ aria-busy="false" aria-expanded="false"
50
+ aria-atomic="false" class="initially-hidden"></ul>
51
+ </form>
52
+ </div>
53
53
 
54
-
55
54
  </div>
56
55
 
56
+
57
+
57
58
  <div id="class-metadata">
58
59
 
59
- <nav id="parent-class-section" class="section">
60
- <h3 class="section-header">Parent</h3>
60
+ <div id="parent-class-section" class="nav-section">
61
+ <h3>Parent</h3>
62
+
61
63
 
62
64
  <p class="link">Object
63
65
 
64
- </nav>
66
+ </div>
65
67
 
66
68
 
69
+
67
70
  <!-- Method Quickref -->
68
- <nav id="method-list-section" class="section">
69
- <h3 class="section-header">Methods</h3>
71
+ <div id="method-list-section" class="nav-section">
72
+ <h3>Methods</h3>
70
73
 
71
- <ul class="link-list">
74
+ <ul class="link-list" role="directory">
72
75
 
73
- <li><a href="#method-c-new">::new</a>
76
+ <li ><a href="#method-c-new">::new</a>
74
77
 
75
- <li><a href="#method-i-flat_profile">#flat_profile</a>
78
+ <li ><a href="#method-i-flat_profile">#flat_profile</a>
76
79
 
77
- <li><a href="#method-i-graph_profile">#graph_profile</a>
80
+ <li ><a href="#method-i-graph_profile">#graph_profile</a>
78
81
 
79
- <li><a href="#method-i-print">#print</a>
82
+ <li ><a href="#method-i-print">#print</a>
80
83
 
81
- <li><a href="#method-i-stack_profile">#stack_profile</a>
84
+ <li ><a href="#method-i-stack_profile">#stack_profile</a>
82
85
 
83
- <li><a href="#method-i-tree_profile">#tree_profile</a>
86
+ <li ><a href="#method-i-tree_profile">#tree_profile</a>
84
87
 
85
88
  </ul>
86
- </nav>
89
+ </div>
87
90
 
88
91
  </div>
89
-
90
- <div id="project-metadata">
91
- <nav id="fileindex-section" class="section project-section">
92
- <h3 class="section-header">Pages</h3>
93
-
94
- <ul>
95
-
96
- <li class="file"><a href="../LICENSE.html">LICENSE</a>
97
-
98
- <li class="file"><a href="../README_rdoc.html">README</a>
99
-
100
- <li class="file"><a href="../examples/flat_txt.html">flat</a>
101
-
102
- <li class="file"><a href="../examples/graph_txt.html">graph</a>
103
-
104
- </ul>
105
92
  </nav>
106
93
 
107
- <nav id="classindex-section" class="section project-section">
108
- <h3 class="section-header">Class and Module Index</h3>
94
+ <main role="main" aria-labelledby="class-RubyProf::MultiPrinter">
95
+ <h1 id="class-RubyProf::MultiPrinter" class="class">
96
+ class RubyProf::MultiPrinter
97
+ </h1>
109
98
 
110
- <ul class="link-list">
111
-
112
- <li><a href="../RubyProf.html">RubyProf</a>
113
-
114
- <li><a href="../RubyProf/AbstractPrinter.html">RubyProf::AbstractPrinter</a>
115
-
116
- <li><a href="../RubyProf/AggregateCallInfo.html">RubyProf::AggregateCallInfo</a>
117
-
118
- <li><a href="../RubyProf/CallInfo.html">RubyProf::CallInfo</a>
119
-
120
- <li><a href="../RubyProf/CallInfoPrinter.html">RubyProf::CallInfoPrinter</a>
121
-
122
- <li><a href="../RubyProf/CallInfoVisitor.html">RubyProf::CallInfoVisitor</a>
123
-
124
- <li><a href="../RubyProf/CallStackPrinter.html">RubyProf::CallStackPrinter</a>
125
-
126
- <li><a href="../RubyProf/CallTreePrinter.html">RubyProf::CallTreePrinter</a>
127
-
128
- <li><a href="../RubyProf/Cmd.html">RubyProf::Cmd</a>
129
-
130
- <li><a href="../RubyProf/DotPrinter.html">RubyProf::DotPrinter</a>
131
-
132
- <li><a href="../RubyProf/FlatPrinter.html">RubyProf::FlatPrinter</a>
133
-
134
- <li><a href="../RubyProf/FlatPrinterWithLineNumbers.html">RubyProf::FlatPrinterWithLineNumbers</a>
135
-
136
- <li><a href="../RubyProf/GraphHtmlPrinter.html">RubyProf::GraphHtmlPrinter</a>
137
-
138
- <li><a href="../RubyProf/GraphPrinter.html">RubyProf::GraphPrinter</a>
139
-
140
- <li><a href="../RubyProf/MethodInfo.html">RubyProf::MethodInfo</a>
141
-
142
- <li><a href="../RubyProf/MultiPrinter.html">RubyProf::MultiPrinter</a>
143
-
144
- <li><a href="../RubyProf/Profile.html">RubyProf::Profile</a>
145
-
146
- <li><a href="../RubyProf/ProfileTask.html">RubyProf::ProfileTask</a>
147
-
148
- <li><a href="../RubyProf/Test.html">RubyProf::Test</a>
149
-
150
- <li><a href="../RubyProf/Thread.html">RubyProf::Thread</a>
151
-
152
- <li><a href="../Rack.html">Rack</a>
153
-
154
- <li><a href="../Rack/RubyProf.html">Rack::RubyProf</a>
155
-
156
- </ul>
157
- </nav>
158
-
159
- </div>
160
- </nav>
161
-
162
- <div id="documentation">
163
- <h1 class="class">class RubyProf::MultiPrinter</h1>
164
-
165
- <div id="description" class="description">
99
+ <section class="description">
166
100
 
167
101
  <p>Helper class to simplify printing profiles of several types from one
168
102
  profiling run. Currently prints a flat profile, a callgrind profile, a call
169
103
  stack profile and a graph profile.</p>
170
104
 
171
- </div><!-- description -->
105
+ </section>
172
106
 
173
107
 
174
108
 
@@ -182,10 +116,11 @@ stack profile and a graph profile.</p>
182
116
 
183
117
 
184
118
 
185
- <!-- Methods -->
186
119
 
187
- <section id="public-class-5Buntitled-5D-method-details" class="method-section section">
188
- <h3 class="section-header">Public Class Methods</h3>
120
+ <section id="public-class-5Buntitled-5D-method-details" class="method-section">
121
+ <header>
122
+ <h3>Public Class Methods</h3>
123
+ </header>
189
124
 
190
125
 
191
126
  <div id="method-c-new" class="method-detail ">
@@ -193,7 +128,9 @@ stack profile and a graph profile.</p>
193
128
  <div class="method-heading">
194
129
  <span class="method-name">new</span><span
195
130
  class="method-args">(result)</span>
131
+
196
132
  <span class="method-click-advice">click to toggle source</span>
133
+
197
134
  </div>
198
135
 
199
136
 
@@ -201,6 +138,7 @@ stack profile and a graph profile.</p>
201
138
 
202
139
 
203
140
 
141
+
204
142
 
205
143
 
206
144
  <div class="method-source-code" id="new-source">
@@ -211,20 +149,22 @@ stack profile and a graph profile.</p>
211
149
  <span class="ruby-ivar">@tree_printer</span> = <span class="ruby-constant">CallTreePrinter</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">result</span>)
212
150
  <span class="ruby-ivar">@flat_printer</span> = <span class="ruby-constant">FlatPrinter</span>.<span class="ruby-identifier">new</span>(<span class="ruby-identifier">result</span>)
213
151
  <span class="ruby-keyword">end</span></pre>
214
- </div><!-- new-source -->
152
+ </div>
215
153
 
216
154
  </div>
217
155
 
218
156
 
219
157
 
220
158
 
221
- </div><!-- new-method -->
159
+ </div>
222
160
 
223
161
 
224
- </section><!-- public-class-method-details -->
162
+ </section>
225
163
 
226
- <section id="public-instance-5Buntitled-5D-method-details" class="method-section section">
227
- <h3 class="section-header">Public Instance Methods</h3>
164
+ <section id="public-instance-5Buntitled-5D-method-details" class="method-section">
165
+ <header>
166
+ <h3>Public Instance Methods</h3>
167
+ </header>
228
168
 
229
169
 
230
170
  <div id="method-i-flat_profile" class="method-detail ">
@@ -232,7 +172,9 @@ stack profile and a graph profile.</p>
232
172
  <div class="method-heading">
233
173
  <span class="method-name">flat_profile</span><span
234
174
  class="method-args">()</span>
175
+
235
176
  <span class="method-click-advice">click to toggle source</span>
177
+
236
178
  </div>
237
179
 
238
180
 
@@ -240,6 +182,7 @@ stack profile and a graph profile.</p>
240
182
 
241
183
  <p>the name of the flat profile file</p>
242
184
 
185
+
243
186
 
244
187
 
245
188
  <div class="method-source-code" id="flat_profile-source">
@@ -247,14 +190,14 @@ stack profile and a graph profile.</p>
247
190
  <span class="ruby-keyword">def</span> <span class="ruby-identifier">flat_profile</span>
248
191
  <span class="ruby-node">&quot;#{@directory}/#{@profile}.flat.txt&quot;</span>
249
192
  <span class="ruby-keyword">end</span></pre>
250
- </div><!-- flat_profile-source -->
193
+ </div>
251
194
 
252
195
  </div>
253
196
 
254
197
 
255
198
 
256
199
 
257
- </div><!-- flat_profile-method -->
200
+ </div>
258
201
 
259
202
 
260
203
  <div id="method-i-graph_profile" class="method-detail ">
@@ -262,7 +205,9 @@ stack profile and a graph profile.</p>
262
205
  <div class="method-heading">
263
206
  <span class="method-name">graph_profile</span><span
264
207
  class="method-args">()</span>
208
+
265
209
  <span class="method-click-advice">click to toggle source</span>
210
+
266
211
  </div>
267
212
 
268
213
 
@@ -270,6 +215,7 @@ stack profile and a graph profile.</p>
270
215
 
271
216
  <p>the name of the graph profile file</p>
272
217
 
218
+
273
219
 
274
220
 
275
221
  <div class="method-source-code" id="graph_profile-source">
@@ -277,14 +223,14 @@ stack profile and a graph profile.</p>
277
223
  <span class="ruby-keyword">def</span> <span class="ruby-identifier">graph_profile</span>
278
224
  <span class="ruby-node">&quot;#{@directory}/#{@profile}.graph.html&quot;</span>
279
225
  <span class="ruby-keyword">end</span></pre>
280
- </div><!-- graph_profile-source -->
226
+ </div>
281
227
 
282
228
  </div>
283
229
 
284
230
 
285
231
 
286
232
 
287
- </div><!-- graph_profile-method -->
233
+ </div>
288
234
 
289
235
 
290
236
  <div id="method-i-print" class="method-detail ">
@@ -292,15 +238,18 @@ stack profile and a graph profile.</p>
292
238
  <div class="method-heading">
293
239
  <span class="method-name">print</span><span
294
240
  class="method-args">(options)</span>
241
+
295
242
  <span class="method-click-advice">click to toggle source</span>
243
+
296
244
  </div>
297
245
 
298
246
 
299
247
  <div class="method-description">
300
248
 
301
- <p>create profile files under <a href="http://:path">options</a> or the
302
- current directory. <a href="http://:profile">options</a> is used as the
303
- base name for the pofile file, defaults to “profile”.</p>
249
+ <p>create profile files under <a href=":path">options</a> or the current
250
+ directory. <a href=":profile">options</a> is used as the base name for the
251
+ pofile file, defaults to “profile”.</p>
252
+
304
253
 
305
254
 
306
255
 
@@ -322,14 +271,14 @@ base name for the pofile file, defaults to “profile”.</p>
322
271
  <span class="ruby-ivar">@flat_printer</span>.<span class="ruby-identifier">print</span>(<span class="ruby-identifier">f</span>, <span class="ruby-identifier">options</span>)
323
272
  <span class="ruby-keyword">end</span>
324
273
  <span class="ruby-keyword">end</span></pre>
325
- </div><!-- print-source -->
274
+ </div>
326
275
 
327
276
  </div>
328
277
 
329
278
 
330
279
 
331
280
 
332
- </div><!-- print-method -->
281
+ </div>
333
282
 
334
283
 
335
284
  <div id="method-i-stack_profile" class="method-detail ">
@@ -337,7 +286,9 @@ base name for the pofile file, defaults to “profile”.</p>
337
286
  <div class="method-heading">
338
287
  <span class="method-name">stack_profile</span><span
339
288
  class="method-args">()</span>
289
+
340
290
  <span class="method-click-advice">click to toggle source</span>
291
+
341
292
  </div>
342
293
 
343
294
 
@@ -345,6 +296,7 @@ base name for the pofile file, defaults to “profile”.</p>
345
296
 
346
297
  <p>the name of the call stack profile file</p>
347
298
 
299
+
348
300
 
349
301
 
350
302
  <div class="method-source-code" id="stack_profile-source">
@@ -352,14 +304,14 @@ base name for the pofile file, defaults to “profile”.</p>
352
304
  <span class="ruby-keyword">def</span> <span class="ruby-identifier">stack_profile</span>
353
305
  <span class="ruby-node">&quot;#{@directory}/#{@profile}.stack.html&quot;</span>
354
306
  <span class="ruby-keyword">end</span></pre>
355
- </div><!-- stack_profile-source -->
307
+ </div>
356
308
 
357
309
  </div>
358
310
 
359
311
 
360
312
 
361
313
 
362
- </div><!-- stack_profile-method -->
314
+ </div>
363
315
 
364
316
 
365
317
  <div id="method-i-tree_profile" class="method-detail ">
@@ -367,7 +319,9 @@ base name for the pofile file, defaults to “profile”.</p>
367
319
  <div class="method-heading">
368
320
  <span class="method-name">tree_profile</span><span
369
321
  class="method-args">()</span>
322
+
370
323
  <span class="method-click-advice">click to toggle source</span>
324
+
371
325
  </div>
372
326
 
373
327
 
@@ -375,6 +329,7 @@ base name for the pofile file, defaults to “profile”.</p>
375
329
 
376
330
  <p>the name of the callgrind profile file</p>
377
331
 
332
+
378
333
 
379
334
 
380
335
  <div class="method-source-code" id="tree_profile-source">
@@ -382,26 +337,25 @@ base name for the pofile file, defaults to “profile”.</p>
382
337
  <span class="ruby-keyword">def</span> <span class="ruby-identifier">tree_profile</span>
383
338
  <span class="ruby-node">&quot;#{@directory}/#{@profile}.grind.dat&quot;</span>
384
339
  <span class="ruby-keyword">end</span></pre>
385
- </div><!-- tree_profile-source -->
340
+ </div>
386
341
 
387
342
  </div>
388
343
 
389
344
 
390
345
 
391
346
 
392
- </div><!-- tree_profile-method -->
347
+ </div>
393
348
 
394
349
 
395
- </section><!-- public-instance-method-details -->
350
+ </section>
396
351
 
397
- </section><!-- 5Buntitled-5D -->
398
-
399
- </div><!-- documentation -->
352
+ </section>
353
+ </main>
400
354
 
401
355
 
402
- <footer id="validator-badges">
403
- <p><a href="http://validator.w3.org/check/referer">[Validate]</a>
404
- <p>Generated by <a href="https://github.com/rdoc/rdoc">RDoc</a> 3.12.1.
405
- <p>Generated with the <a href="http://deveiate.org/projects/Darkfish-Rdoc/">Darkfish Rdoc Generator</a> 3.
356
+ <footer id="validator-badges" role="contentinfo">
357
+ <p><a href="http://validator.w3.org/check/referer">Validate</a>
358
+ <p>Generated by <a href="http://rdoc.rubyforge.org">RDoc</a> 4.1.0.
359
+ <p>Based on <a href="http://deveiate.org/projects/Darkfish-Rdoc/">Darkfish</a> by <a href="http://deveiate.org">Michael Granger</a>.
406
360
  </footer>
407
361