hotch 0.3.0 → 0.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 147bda4de32c92615369a89ef1bd9ce1affd6f2e
4
- data.tar.gz: dd39ec72f47e2763064ccc97da333634fdb0b298
3
+ metadata.gz: c35cd590d82f32eb2e073d78b2dcf3a59f9dac26
4
+ data.tar.gz: 0043e7a301ab0c4ede090e614723ca40657f172e
5
5
  SHA512:
6
- metadata.gz: eb1907ea105080e2153e7e61823fb04ab73720ebc069b5bd1d9e17e5d6eb854c2e1db084b2bbe6312f1f782845b6b06eafee7b7ce3d54563bb8ca7d33325e15e
7
- data.tar.gz: 2a738b6d8950d50f7349a699a5ca323fe1f4c32c8a65a0d81fd0b9f2f29d3388a96ed0e46750755d583e59b9bcf44bb1f0873e54b7f6c94dfa35c1c0149add69
6
+ metadata.gz: 85a612b48a755637431d2827db351df62ca9667837de967ffe1d7b71b9895b054a5bc46245d1d4432dbfa048a42a1381941c38edf92e77b955458cc8be6f31eb
7
+ data.tar.gz: 540d85864f5f6c3a88b6f3de0a04ade4af677d317d2799fc01a8b93de1aa423014ff4b66df68125006b4e90451dd9a585797358c55308f8e5a049a09dd8c1051
data/README.md CHANGED
@@ -1,20 +1,68 @@
1
1
  # Hotch
2
2
 
3
+ [![Gem Version](https://img.shields.io/gem/v/hotch.svg)](https://rubygems.org/gems/hotch)
4
+ [![Source code](https://img.shields.io/badge/code-GitHub-blue.svg)](https://github.com/splattael/hotch)
5
+
3
6
  Profile helper
4
7
 
5
8
  ## What?
6
9
 
7
- * Wraps your program run with [stackprof](https://github.com/tmm1/stackprof)
10
+ ### Callstack profiler
11
+
12
+ * Wraps your program run with [stackprof](https://rubygems.org/gems/stackprof)
8
13
  * Dumps profile results
9
- * Converts profile dump using `graphviz` (dot) to SVG
10
- * Optionally shows the call-stack graph
14
+ * Converts a profile dump using [graphviz](http://www.graphviz.org/) (dot) to SVG
15
+ * Optionally shows the call-stack graph after program exit
16
+
17
+ ### Memory profiler
18
+
19
+ * Traces memory allocation using [allocation_tracer](https://rubygems.org/gems/allocation_tracer)
20
+ * Prints the results formatted and sorted by object count
21
+
22
+ ## Example
23
+
24
+ ### Callstack profiler
25
+
26
+ From [dry-validation](https://github.com/dry-rb/dry-validation) [benchmarks/profile_schema_call_valid.rb](https://github.com/dry-rb/dry-validation/blob/3d090eeafac9d1c31fdc3e054f8fd5ec900e12f9/benchmarks/profile_schema_call_valid.rb):
27
+
28
+ ![dry-validation](images/dry-validation.profile_schema_call_valid.png?raw=true "benchmarks/profile_schema_call_valid.rb")
29
+
30
+ ### Memory profiler
31
+
32
+ ```
33
+ filename type count old_count total_age min_age max_age total_memsize
34
+ inline.rb:28 T_IMEMO 1 0 0 0 0 0
35
+ dry/struct/class_interface.rb:74 T_IMEMO 1 0 0 0 0 0
36
+ dry/struct/class_interface.rb:77 T_IMEMO 1 0 0 0 0 0
37
+ dry/types/decorator.rb:28 T_IMEMO 1 0 0 0 0 0
38
+ dry/types/hash/schema.rb:96 T_IMEMO 2 0 0 0 0 0
39
+ dry/types/hash/schema.rb:52 T_IMEMO 2 0 0 0 0 0
40
+ inline.rb:27 T_STRING 1000 0 0 0 0 0
41
+ inline.rb:28 T_HASH 1000 0 0 0 0 0
42
+ inline.rb:26 T_HASH 1000 0 0 0 0 0
43
+ dry/types/hash/schema.rb:92 T_HASH 2000 0 0 0 0 0
44
+ dry/types/hash/schema.rb:60 T_HASH 2000 0 0 0 0 0
45
+ dry/logic/rule.rb:0 T_ARRAY 2000 0 0 0 0 0
46
+ dry/logic/rule.rb:47 T_OBJECT 2000 0 0 0 0 0
47
+ dry/types/definition.rb:59 T_OBJECT 2000 0 0 0 0 0
48
+ dry/struct/class_interface.rb:77 T_OBJECT 2000 0 0 0 0 0
49
+ dry/types/constrained.rb:20 T_DATA 4000 0 0 0 0 0
50
+ dry/types/constrained.rb:27 T_ARRAY 4000 0 0 0 0 0
51
+ dry/logic/rule.rb:47 T_ARRAY 4000 0 0 0 0 0
52
+ dry/logic/rule.rb:47 T_DATA 4000 0 0 0 0 0
53
+ dry/types/definition.rb:51 T_ARRAY 4000 0 0 0 0 0
54
+ dry/types/hash/schema.rb:92 T_ARRAY 6000 0 0 0 0 0
55
+ dry/struct.rb:16 T_STRING 6000 0 0 0 0 0
56
+ TOTAL 47008 0 0 0 0 0
57
+ ```
58
+
11
59
 
12
60
  ## Installation
13
61
 
14
62
  Add this line to your application's Gemfile:
15
63
 
16
64
  ```ruby
17
- gem 'hotch'
65
+ gem 'hotch', '~> 0.4.0'
18
66
  ```
19
67
 
20
68
  And then execute:
@@ -88,6 +136,46 @@ Hotch::Minitest.run(options: <stackprof options>)
88
136
  Hotch::Minitest.run(options: { limit: 200 })
89
137
  ```
90
138
 
139
+ ### Memory profiler
140
+
141
+ Require `hotch/memory` and use `Hotch.memory { ... }` as in:
142
+
143
+ ```ruby
144
+ require "bundler/setup"
145
+
146
+ require "dry-types"
147
+ require "dry-struct"
148
+ require "hotch/memory"
149
+
150
+ module Types
151
+ class IntStruct < Dry::Struct
152
+ include Dry::Types.module
153
+ constructor_type :strict
154
+ attribute :int, Strict::Int
155
+ end
156
+
157
+ class Success < Dry::Struct
158
+ include Dry::Types.module
159
+ constructor_type :strict
160
+ attribute :string, Strict::String
161
+ attribute :sub, Types::IntStruct
162
+ end
163
+ end
164
+
165
+ # For more stable results
166
+ GC.disable
167
+
168
+ Hotch.memory do
169
+ 1000.times do
170
+ Types::Success.new(
171
+ :string => "string",
172
+ :sub => Types::IntStruct.new(:int => 1)
173
+ )
174
+ end
175
+ end
176
+ ```
177
+
178
+
91
179
  ## Caveat
92
180
 
93
181
  ### Using with bundler
@@ -106,6 +194,9 @@ If you use `hotch` in project managed by `bundler` you have to specify `hotch` i
106
194
 
107
195
  Follow these steps to release this gem:
108
196
 
197
+ # Increase version
109
198
  edit lib/hotch/version.rb
199
+ edit README.md
200
+ # Commit
110
201
  git commit -m "Release vX.Y.Z"
111
202
  rake release
@@ -18,7 +18,8 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_runtime_dependency "stackprof", "~> 0.2.9"
21
+ spec.add_runtime_dependency "stackprof", "~> 0.2.10"
22
+ spec.add_runtime_dependency "allocation_tracer", "~> 0.6.3"
22
23
 
23
24
  spec.add_development_dependency "bundler", "~> 1.7"
24
25
  spec.add_development_dependency "rake", "~> 10.0"
@@ -0,0 +1,609 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
3
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
+ <!-- Generated by graphviz version 2.38.0 (20140413.2041)
5
+ -->
6
+ <!-- Title: profile Pages: 1 -->
7
+ <svg width="2043pt" height="2005pt"
8
+ viewBox="0.00 0.00 2043.00 2005.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
9
+ <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 2001)">
10
+ <title>profile</title>
11
+ <polygon fill="white" stroke="none" points="-4,4 -4,-2001 2039,-2001 2039,4 -4,4"/>
12
+ <!-- Legend -->
13
+ <g id="node1" class="node"><title>Legend</title>
14
+ <text text-anchor="start" x="475" y="-1945.8" font-family="Times,serif" font-size="24.00">Total samples: 546</text>
15
+ </g>
16
+ <!-- 14699180 -->
17
+ <g id="node2" class="node"><title>14699180</title>
18
+ <polygon fill="none" stroke="black" stroke-width="4.19231" points="766.5,-1792 678.5,-1792 678.5,-1751 766.5,-1751 766.5,-1792"/>
19
+ <text text-anchor="middle" x="722.5" y="-1780" font-family="Times,serif" font-size="10.00">Object#Hotch</text>
20
+ <text text-anchor="end" x="758.5" y="-1769" font-family="Times,serif" font-size="10.00">0 (0.0%)</text>
21
+ <text text-anchor="end" x="758.5" y="-1758" font-family="Times,serif" font-size="10.00">of 1008 (184.6%)</text>
22
+ </g>
23
+ <!-- 19001160 -->
24
+ <g id="node8" class="node"><title>19001160</title>
25
+ <polygon fill="none" stroke="black" stroke-width="2.34615" points="710,-1700 625,-1700 625,-1659 710,-1659 710,-1700"/>
26
+ <text text-anchor="middle" x="667.5" y="-1688" font-family="Times,serif" font-size="10.00">block in &lt;main&gt;</text>
27
+ <text text-anchor="end" x="702" y="-1677" font-family="Times,serif" font-size="10.00">0 (0.0%)</text>
28
+ <text text-anchor="end" x="702" y="-1666" font-family="Times,serif" font-size="10.00">of 504 (92.3%)</text>
29
+ </g>
30
+ <!-- 14699180&#45;&gt;19001160 -->
31
+ <g id="edge1" class="edge"><title>14699180&#45;&gt;19001160</title>
32
+ <path fill="none" stroke="black" stroke-width="2.34615" d="M706.086,-1750.79C701.758,-1745.2 697.254,-1739 693.5,-1733 688.898,-1725.64 684.475,-1717.36 680.624,-1709.58"/>
33
+ <polygon fill="black" stroke="black" stroke-width="2.34615" points="683.72,-1707.95 676.236,-1700.45 677.41,-1710.98 683.72,-1707.95"/>
34
+ <text text-anchor="middle" x="704" y="-1721.8" font-family="Times,serif" font-size="14.00">504</text>
35
+ </g>
36
+ <!-- 14699580 -->
37
+ <g id="node9" class="node"><title>14699580</title>
38
+ <polygon fill="none" stroke="black" stroke-width="2.34615" points="805,-1700 728,-1700 728,-1659 805,-1659 805,-1700"/>
39
+ <text text-anchor="middle" x="766.5" y="-1688" font-family="Times,serif" font-size="10.00">Hotch#run</text>
40
+ <text text-anchor="end" x="797" y="-1677" font-family="Times,serif" font-size="10.00">0 (0.0%)</text>
41
+ <text text-anchor="end" x="797" y="-1666" font-family="Times,serif" font-size="10.00">of 504 (92.3%)</text>
42
+ </g>
43
+ <!-- 14699180&#45;&gt;14699580 -->
44
+ <g id="edge2" class="edge"><title>14699180&#45;&gt;14699580</title>
45
+ <path fill="none" stroke="black" stroke-width="2.34615" d="M719.192,-1750.94C718.345,-1740.68 718.761,-1728.16 723.5,-1718 725.194,-1714.37 727.427,-1710.95 729.986,-1707.76"/>
46
+ <polygon fill="black" stroke="black" stroke-width="2.34615" points="732.644,-1710.04 736.899,-1700.34 727.522,-1705.27 732.644,-1710.04"/>
47
+ <text text-anchor="middle" x="734" y="-1721.8" font-family="Times,serif" font-size="14.00">504</text>
48
+ </g>
49
+ <!-- 17603140 -->
50
+ <g id="node3" class="node"><title>17603140</title>
51
+ <polygon fill="none" stroke="black" stroke-width="4.07509" points="766,-1424 569,-1424 569,-1368 766,-1368 766,-1424"/>
52
+ <text text-anchor="middle" x="667.5" y="-1408.32" font-family="Times,serif" font-size="14.60">Dry::Validation::Executor#call</text>
53
+ <text text-anchor="end" x="758" y="-1392.32" font-family="Times,serif" font-size="14.60">12 (2.2%)</text>
54
+ <text text-anchor="end" x="758" y="-1376.32" font-family="Times,serif" font-size="14.60">of 976 (178.8%)</text>
55
+ </g>
56
+ <!-- 17603140&#45;&gt;17603140 -->
57
+ <g id="edge4" class="edge"><title>17603140&#45;&gt;17603140</title>
58
+ <path fill="none" stroke="black" stroke-width="2.2619" d="M766.091,-1404.2C776.974,-1402.64 784,-1399.91 784,-1396 784,-1393.5 781.116,-1391.47 776.182,-1389.93"/>
59
+ <polygon fill="black" stroke="black" stroke-width="2.2619" points="776.599,-1386.44 766.091,-1387.8 775.15,-1393.29 776.599,-1386.44"/>
60
+ <text text-anchor="middle" x="794.5" y="-1392.3" font-family="Times,serif" font-size="14.00">481</text>
61
+ </g>
62
+ <!-- 17604000 -->
63
+ <g id="node4" class="node"><title>17604000</title>
64
+ <polygon fill="none" stroke="black" stroke-width="3.90293" points="767.5,-1317 567.5,-1317 567.5,-1264 767.5,-1264 767.5,-1317"/>
65
+ <text text-anchor="middle" x="667.5" y="-1301.93" font-family="Times,serif" font-size="13.84">Dry::Validation::ApplyRules#call</text>
66
+ <text text-anchor="end" x="759.5" y="-1286.93" font-family="Times,serif" font-size="13.84">10 (1.8%)</text>
67
+ <text text-anchor="end" x="759.5" y="-1271.93" font-family="Times,serif" font-size="13.84">of 929 (170.1%)</text>
68
+ </g>
69
+ <!-- 17603140&#45;&gt;17604000 -->
70
+ <g id="edge3" class="edge"><title>17603140&#45;&gt;17604000</title>
71
+ <path fill="none" stroke="black" stroke-width="2.2033" d="M667.5,-1367.81C667.5,-1355.42 667.5,-1340.6 667.5,-1327.33"/>
72
+ <polygon fill="black" stroke="black" stroke-width="2.2033" points="671,-1327.09 667.5,-1317.09 664,-1327.09 671,-1327.09"/>
73
+ <text text-anchor="middle" x="678" y="-1338.8" font-family="Times,serif" font-size="14.00">465</text>
74
+ </g>
75
+ <!-- 17603440 -->
76
+ <g id="node34" class="node"><title>17603440</title>
77
+ <polygon fill="none" stroke="black" stroke-width="0.587912" points="986,-1312.5 825,-1312.5 825,-1268.5 986,-1268.5 986,-1312.5"/>
78
+ <text text-anchor="middle" x="905.5" y="-1299.89" font-family="Times,serif" font-size="10.77">Dry::Validation::BuildErrors#call</text>
79
+ <text text-anchor="end" x="978" y="-1287.89" font-family="Times,serif" font-size="10.77">2 (0.4%)</text>
80
+ <text text-anchor="end" x="978" y="-1275.89" font-family="Times,serif" font-size="10.77">of 24 (4.4%)</text>
81
+ </g>
82
+ <!-- 17603140&#45;&gt;17603440 -->
83
+ <g id="edge5" class="edge"><title>17603140&#45;&gt;17603440</title>
84
+ <path fill="none" stroke="black" stroke-width="0.547619" d="M729.721,-1367.94C766.259,-1352.05 812.126,-1332.11 847.844,-1316.57"/>
85
+ <polygon fill="black" stroke="black" stroke-width="0.547619" points="849.388,-1319.72 857.163,-1312.52 846.597,-1313.3 849.388,-1319.72"/>
86
+ <text text-anchor="middle" x="807.5" y="-1338.8" font-family="Times,serif" font-size="14.00">13</text>
87
+ </g>
88
+ <!-- 17604440 -->
89
+ <g id="node41" class="node"><title>17604440</title>
90
+ <polygon fill="none" stroke="black" stroke-width="0.518315" points="1201,-1312.5 1036,-1312.5 1036,-1268.5 1201,-1268.5 1201,-1312.5"/>
91
+ <text text-anchor="middle" x="1118.5" y="-1299.89" font-family="Times,serif" font-size="10.77">Dry::Validation::ProcessInput#call</text>
92
+ <text text-anchor="end" x="1193" y="-1287.89" font-family="Times,serif" font-size="10.77">2 (0.4%)</text>
93
+ <text text-anchor="end" x="1193" y="-1275.89" font-family="Times,serif" font-size="10.77">of 5 (0.9%)</text>
94
+ </g>
95
+ <!-- 17603140&#45;&gt;17604440 -->
96
+ <g id="edge6" class="edge"><title>17603140&#45;&gt;17604440</title>
97
+ <path fill="none" stroke="black" stroke-width="0.518315" d="M766.038,-1375.31C838.597,-1360.41 939.52,-1338.84 1027.5,-1317 1029.94,-1316.39 1032.41,-1315.77 1034.9,-1315.13"/>
98
+ <polygon fill="black" stroke="black" stroke-width="0.518315" points="1035.8,-1318.51 1044.6,-1312.61 1034.04,-1311.74 1035.8,-1318.51"/>
99
+ <text text-anchor="middle" x="952" y="-1338.8" font-family="Times,serif" font-size="14.00">5</text>
100
+ </g>
101
+ <!-- 17604000&#45;&gt;17604000 -->
102
+ <g id="edge8" class="edge"><title>17604000&#45;&gt;17604000</title>
103
+ <path fill="none" stroke="black" stroke-width="2.19963" d="M767.788,-1298.64C778.567,-1297.07 785.5,-1294.36 785.5,-1290.5 785.5,-1288.03 782.655,-1286.03 777.775,-1284.49"/>
104
+ <polygon fill="black" stroke="black" stroke-width="2.19963" points="778.298,-1281.03 767.788,-1282.36 776.835,-1287.87 778.298,-1281.03"/>
105
+ <text text-anchor="middle" x="796" y="-1286.8" font-family="Times,serif" font-size="14.00">464</text>
106
+ </g>
107
+ <!-- 12226280 -->
108
+ <g id="node5" class="node"><title>12226280</title>
109
+ <polygon fill="none" stroke="black" stroke-width="3.42308" points="750.5,-1213 584.5,-1213 584.5,-1172 750.5,-1172 750.5,-1213"/>
110
+ <text text-anchor="middle" x="667.5" y="-1201" font-family="Times,serif" font-size="10.00">Dry::Logic::Rule::Conjunction#call</text>
111
+ <text text-anchor="end" x="742.5" y="-1190" font-family="Times,serif" font-size="10.00">0 (0.0%)</text>
112
+ <text text-anchor="end" x="742.5" y="-1179" font-family="Times,serif" font-size="10.00">of 798 (146.2%)</text>
113
+ </g>
114
+ <!-- 17604000&#45;&gt;12226280 -->
115
+ <g id="edge7" class="edge"><title>17604000&#45;&gt;12226280</title>
116
+ <path fill="none" stroke="black" stroke-width="2.16667" d="M667.5,-1263.77C667.5,-1251.36 667.5,-1236.4 667.5,-1223.48"/>
117
+ <polygon fill="black" stroke="black" stroke-width="2.16667" points="671,-1223.2 667.5,-1213.2 664,-1223.2 671,-1223.2"/>
118
+ <text text-anchor="middle" x="678" y="-1234.8" font-family="Times,serif" font-size="14.00">455</text>
119
+ </g>
120
+ <!-- 12226280&#45;&gt;12226280 -->
121
+ <g id="edge10" class="edge"><title>12226280&#45;&gt;12226280</title>
122
+ <path fill="none" stroke="black" stroke-width="1.75641" d="M750.708,-1200.06C761.422,-1198.75 768.5,-1196.23 768.5,-1192.5 768.5,-1190.11 765.595,-1188.22 760.691,-1186.82"/>
123
+ <polygon fill="black" stroke="black" stroke-width="1.75641" points="761.184,-1183.35 750.708,-1184.94 759.887,-1190.23 761.184,-1183.35"/>
124
+ <text text-anchor="middle" x="779" y="-1188.8" font-family="Times,serif" font-size="14.00">343</text>
125
+ </g>
126
+ <!-- 12405940 -->
127
+ <g id="node12" class="node"><title>12405940</title>
128
+ <polygon fill="none" stroke="black" stroke-width="2.10806" points="751.5,-1120 583.5,-1120 583.5,-1070 751.5,-1070 751.5,-1120"/>
129
+ <text text-anchor="middle" x="667.5" y="-1105.85" font-family="Times,serif" font-size="12.68">Dry::Logic::Rule::Value#call</text>
130
+ <text text-anchor="end" x="743.5" y="-1091.85" font-family="Times,serif" font-size="12.68">7 (1.3%)</text>
131
+ <text text-anchor="end" x="743.5" y="-1077.85" font-family="Times,serif" font-size="12.68">of 439 (80.4%)</text>
132
+ </g>
133
+ <!-- 12226280&#45;&gt;12405940 -->
134
+ <g id="edge9" class="edge"><title>12226280&#45;&gt;12405940</title>
135
+ <path fill="none" stroke="black" stroke-width="2.10806" d="M667.5,-1171.71C667.5,-1159.78 667.5,-1144.26 667.5,-1130.38"/>
136
+ <polygon fill="black" stroke="black" stroke-width="2.10806" points="671,-1130.17 667.5,-1120.17 664,-1130.17 671,-1130.17"/>
137
+ <text text-anchor="middle" x="678" y="-1142.8" font-family="Times,serif" font-size="14.00">439</text>
138
+ </g>
139
+ <!-- 12122060 -->
140
+ <g id="node32" class="node"><title>12122060</title>
141
+ <polygon fill="none" stroke="black" stroke-width="0.598901" points="1027,-1121 770,-1121 770,-1069 1027,-1069 1027,-1121"/>
142
+ <text text-anchor="middle" x="898.5" y="-1100.72" font-family="Times,serif" font-size="20.36">Dry::Logic::Result#success?</text>
143
+ <text text-anchor="end" x="1019" y="-1078.72" font-family="Times,serif" font-size="20.36">27 (4.9%)</text>
144
+ </g>
145
+ <!-- 12226280&#45;&gt;12122060 -->
146
+ <g id="edge11" class="edge"><title>12226280&#45;&gt;12122060</title>
147
+ <path fill="none" stroke="black" stroke-width="0.558608" d="M714.804,-1171.94C747.398,-1158.47 791.281,-1140.33 827.983,-1125.15"/>
148
+ <polygon fill="black" stroke="black" stroke-width="0.558608" points="829.732,-1128.22 837.636,-1121.16 827.058,-1121.75 829.732,-1128.22"/>
149
+ <text text-anchor="middle" x="796.5" y="-1142.8" font-family="Times,serif" font-size="14.00">16</text>
150
+ </g>
151
+ <!-- 17601700 -->
152
+ <g id="node6" class="node"><title>17601700</title>
153
+ <polygon fill="none" stroke="black" stroke-width="2.34615" points="737.5,-1516 597.5,-1516 597.5,-1475 737.5,-1475 737.5,-1516"/>
154
+ <text text-anchor="middle" x="667.5" y="-1504" font-family="Times,serif" font-size="10.00">Dry::Validation::Schema#call</text>
155
+ <text text-anchor="end" x="729.5" y="-1493" font-family="Times,serif" font-size="10.00">0 (0.0%)</text>
156
+ <text text-anchor="end" x="729.5" y="-1482" font-family="Times,serif" font-size="10.00">of 504 (92.3%)</text>
157
+ </g>
158
+ <!-- 17601700&#45;&gt;17603140 -->
159
+ <g id="edge12" class="edge"><title>17601700&#45;&gt;17603140</title>
160
+ <path fill="none" stroke="black" stroke-width="2.31319" d="M667.5,-1474.77C667.5,-1463.15 667.5,-1448.08 667.5,-1434.3"/>
161
+ <polygon fill="black" stroke="black" stroke-width="2.31319" points="671,-1434.09 667.5,-1424.09 664,-1434.09 671,-1434.09"/>
162
+ <text text-anchor="middle" x="678" y="-1445.8" font-family="Times,serif" font-size="14.00">495</text>
163
+ </g>
164
+ <!-- 10194360 -->
165
+ <g id="node37" class="node"><title>10194360</title>
166
+ <polygon fill="none" stroke="black" stroke-width="0.532967" points="981.5,-1416.5 823.5,-1416.5 823.5,-1375.5 981.5,-1375.5 981.5,-1416.5"/>
167
+ <text text-anchor="middle" x="902.5" y="-1404.19" font-family="Times,serif" font-size="10.38">Dry::Validation::Result#initialize</text>
168
+ <text text-anchor="end" x="973.5" y="-1393.19" font-family="Times,serif" font-size="10.38">1 (0.2%)</text>
169
+ <text text-anchor="end" x="973.5" y="-1382.19" font-family="Times,serif" font-size="10.38">of 9 (1.6%)</text>
170
+ </g>
171
+ <!-- 17601700&#45;&gt;10194360 -->
172
+ <g id="edge13" class="edge"><title>17601700&#45;&gt;10194360</title>
173
+ <path fill="none" stroke="black" stroke-width="0.532967" d="M714.773,-1474.89C752.618,-1459.18 805.817,-1437.11 845.924,-1420.47"/>
174
+ <polygon fill="black" stroke="black" stroke-width="0.532967" points="847.407,-1423.65 855.302,-1416.58 844.725,-1417.18 847.407,-1423.65"/>
175
+ <text text-anchor="middle" x="795" y="-1445.8" font-family="Times,serif" font-size="14.00">9</text>
176
+ </g>
177
+ <!-- 19001060 -->
178
+ <g id="node7" class="node"><title>19001060</title>
179
+ <polygon fill="none" stroke="black" stroke-width="2.34615" points="730,-1608 605,-1608 605,-1567 730,-1567 730,-1608"/>
180
+ <text text-anchor="middle" x="667.5" y="-1596" font-family="Times,serif" font-size="10.00">block (2 levels) in &lt;main&gt;</text>
181
+ <text text-anchor="end" x="722" y="-1585" font-family="Times,serif" font-size="10.00">0 (0.0%)</text>
182
+ <text text-anchor="end" x="722" y="-1574" font-family="Times,serif" font-size="10.00">of 504 (92.3%)</text>
183
+ </g>
184
+ <!-- 19001060&#45;&gt;17601700 -->
185
+ <g id="edge14" class="edge"><title>19001060&#45;&gt;17601700</title>
186
+ <path fill="none" stroke="black" stroke-width="2.34615" d="M667.5,-1566.97C667.5,-1555.14 667.5,-1539.81 667.5,-1526.47"/>
187
+ <polygon fill="black" stroke="black" stroke-width="2.34615" points="671,-1526.3 667.5,-1516.3 664,-1526.3 671,-1526.3"/>
188
+ <text text-anchor="middle" x="678" y="-1537.8" font-family="Times,serif" font-size="14.00">504</text>
189
+ </g>
190
+ <!-- 19001160&#45;&gt;19001060 -->
191
+ <g id="edge15" class="edge"><title>19001160&#45;&gt;19001060</title>
192
+ <path fill="none" stroke="black" stroke-width="2.34615" d="M667.5,-1658.97C667.5,-1647.14 667.5,-1631.81 667.5,-1618.47"/>
193
+ <polygon fill="black" stroke="black" stroke-width="2.34615" points="671,-1618.3 667.5,-1608.3 664,-1618.3 671,-1618.3"/>
194
+ <text text-anchor="middle" x="678" y="-1629.8" font-family="Times,serif" font-size="14.00">504</text>
195
+ </g>
196
+ <!-- 14699580&#45;&gt;14699180 -->
197
+ <g id="edge16" class="edge"><title>14699580&#45;&gt;14699180</title>
198
+ <path fill="none" stroke="black" stroke-width="2.34615" d="M758.961,-1700.23C754.969,-1710.19 749.804,-1722.39 744.5,-1733 743.015,-1735.97 741.39,-1739.03 739.718,-1742.05"/>
199
+ <polygon fill="black" stroke="black" stroke-width="2.34615" points="736.572,-1740.5 734.65,-1750.92 742.65,-1743.98 736.572,-1740.5"/>
200
+ <text text-anchor="middle" x="761" y="-1721.8" font-family="Times,serif" font-size="14.00">504</text>
201
+ </g>
202
+ <!-- 19001740 -->
203
+ <g id="node10" class="node"><title>19001740</title>
204
+ <polygon fill="none" stroke="black" stroke-width="2.34615" points="761,-1884 684,-1884 684,-1843 761,-1843 761,-1884"/>
205
+ <text text-anchor="middle" x="722.5" y="-1872" font-family="Times,serif" font-size="10.00">&lt;main&gt;</text>
206
+ <text text-anchor="end" x="753" y="-1861" font-family="Times,serif" font-size="10.00">0 (0.0%)</text>
207
+ <text text-anchor="end" x="753" y="-1850" font-family="Times,serif" font-size="10.00">of 504 (92.3%)</text>
208
+ </g>
209
+ <!-- 19001740&#45;&gt;14699180 -->
210
+ <g id="edge17" class="edge"><title>19001740&#45;&gt;14699180</title>
211
+ <path fill="none" stroke="black" stroke-width="2.34615" d="M722.5,-1842.97C722.5,-1831.14 722.5,-1815.81 722.5,-1802.47"/>
212
+ <polygon fill="black" stroke="black" stroke-width="2.34615" points="726,-1802.3 722.5,-1792.3 719,-1802.3 726,-1802.3"/>
213
+ <text text-anchor="middle" x="733" y="-1813.8" font-family="Times,serif" font-size="14.00">504</text>
214
+ </g>
215
+ <!-- 9023860 -->
216
+ <g id="node11" class="node"><title>9023860</title>
217
+ <polygon fill="none" stroke="black" stroke-width="2.34615" points="761,-1986.5 684,-1986.5 684,-1945.5 761,-1945.5 761,-1986.5"/>
218
+ <text text-anchor="middle" x="722.5" y="-1974.5" font-family="Times,serif" font-size="10.00">&lt;main&gt;</text>
219
+ <text text-anchor="end" x="753" y="-1963.5" font-family="Times,serif" font-size="10.00">0 (0.0%)</text>
220
+ <text text-anchor="end" x="753" y="-1952.5" font-family="Times,serif" font-size="10.00">of 504 (92.3%)</text>
221
+ </g>
222
+ <!-- 9023860&#45;&gt;19001740 -->
223
+ <g id="edge18" class="edge"><title>9023860&#45;&gt;19001740</title>
224
+ <path fill="none" stroke="black" stroke-width="2.34615" d="M722.5,-1945.14C722.5,-1930.69 722.5,-1910.86 722.5,-1894.49"/>
225
+ <polygon fill="black" stroke="black" stroke-width="2.34615" points="726,-1894.31 722.5,-1884.31 719,-1894.31 726,-1894.31"/>
226
+ <text text-anchor="middle" x="733" y="-1905.8" font-family="Times,serif" font-size="14.00">504</text>
227
+ </g>
228
+ <!-- 12405840 -->
229
+ <g id="node14" class="node"><title>12405840</title>
230
+ <polygon fill="none" stroke="black" stroke-width="1.21429" points="558,-1018 395,-1018 395,-971 558,-971 558,-1018"/>
231
+ <text text-anchor="middle" x="476.5" y="-1004.47" font-family="Times,serif" font-size="11.92">Dry::Logic::Rule::Value#apply</text>
232
+ <text text-anchor="end" x="550" y="-991.466" font-family="Times,serif" font-size="11.92">5 (0.9%)</text>
233
+ <text text-anchor="end" x="550" y="-978.466" font-family="Times,serif" font-size="11.92">of 195 (35.7%)</text>
234
+ </g>
235
+ <!-- 12405940&#45;&gt;12405840 -->
236
+ <g id="edge19" class="edge"><title>12405940&#45;&gt;12405840</title>
237
+ <path fill="none" stroke="black" stroke-width="1.21429" d="M620.776,-1069.9C593.172,-1055.67 558.135,-1037.6 529.502,-1022.83"/>
238
+ <polygon fill="black" stroke="black" stroke-width="1.21429" points="530.94,-1019.64 520.448,-1018.16 527.731,-1025.86 530.94,-1019.64"/>
239
+ <text text-anchor="middle" x="593" y="-1039.8" font-family="Times,serif" font-size="14.00">195</text>
240
+ </g>
241
+ <!-- 12123120 -->
242
+ <g id="node16" class="node"><title>12123120</title>
243
+ <polygon fill="none" stroke="black" stroke-width="0.932234" points="759,-1016.5 576,-1016.5 576,-972.5 759,-972.5 759,-1016.5"/>
244
+ <text text-anchor="middle" x="667.5" y="-1003.89" font-family="Times,serif" font-size="10.77">#&lt;Module:0x0000000181f1b8&gt;.Result</text>
245
+ <text text-anchor="end" x="751" y="-991.886" font-family="Times,serif" font-size="10.77">2 (0.4%)</text>
246
+ <text text-anchor="end" x="751" y="-979.886" font-family="Times,serif" font-size="10.77">of 118 (21.6%)</text>
247
+ </g>
248
+ <!-- 12405940&#45;&gt;12123120 -->
249
+ <g id="edge21" class="edge"><title>12405940&#45;&gt;12123120</title>
250
+ <path fill="none" stroke="black" stroke-width="0.932234" d="M667.5,-1069.9C667.5,-1056.92 667.5,-1040.76 667.5,-1026.81"/>
251
+ <polygon fill="black" stroke="black" stroke-width="0.932234" points="671,-1026.67 667.5,-1016.67 664,-1026.67 671,-1026.67"/>
252
+ <text text-anchor="middle" x="678" y="-1039.8" font-family="Times,serif" font-size="14.00">118</text>
253
+ </g>
254
+ <!-- 12406140 -->
255
+ <g id="node21" class="node"><title>12406140</title>
256
+ <polygon fill="none" stroke="black" stroke-width="0.734432" points="949.5,-1018 777.5,-1018 777.5,-971 949.5,-971 949.5,-1018"/>
257
+ <text text-anchor="middle" x="863.5" y="-1004.47" font-family="Times,serif" font-size="11.92">Dry::Logic::Rule::Value#nulary?</text>
258
+ <text text-anchor="end" x="941.5" y="-991.466" font-family="Times,serif" font-size="11.92">5 (0.9%)</text>
259
+ <text text-anchor="end" x="941.5" y="-978.466" font-family="Times,serif" font-size="11.92">of 64 (11.7%)</text>
260
+ </g>
261
+ <!-- 12405940&#45;&gt;12406140 -->
262
+ <g id="edge20" class="edge"><title>12405940&#45;&gt;12406140</title>
263
+ <path fill="none" stroke="black" stroke-width="0.734432" d="M715.447,-1069.9C743.774,-1055.67 779.728,-1037.6 809.111,-1022.83"/>
264
+ <polygon fill="black" stroke="black" stroke-width="0.734432" points="811.038,-1025.78 818.402,-1018.16 807.895,-1019.53 811.038,-1025.78"/>
265
+ <text text-anchor="middle" x="783.5" y="-1039.8" font-family="Times,serif" font-size="14.00">64</text>
266
+ </g>
267
+ <!-- 12352900 -->
268
+ <g id="node27" class="node"><title>12352900</title>
269
+ <polygon fill="none" stroke="black" stroke-width="0.686813" points="1119.5,-1015 967.5,-1015 967.5,-974 1119.5,-974 1119.5,-1015"/>
270
+ <text text-anchor="middle" x="1043.5" y="-1002.69" font-family="Times,serif" font-size="10.38">Dry::Logic::Rule::Key#evaluate</text>
271
+ <text text-anchor="end" x="1111.5" y="-991.693" font-family="Times,serif" font-size="10.38">1 (0.2%)</text>
272
+ <text text-anchor="end" x="1111.5" y="-980.693" font-family="Times,serif" font-size="10.38">of 51 (9.3%)</text>
273
+ </g>
274
+ <!-- 12405940&#45;&gt;12352900 -->
275
+ <g id="edge22" class="edge"><title>12405940&#45;&gt;12352900</title>
276
+ <path fill="none" stroke="black" stroke-width="0.686813" d="M751.54,-1071.62C754.903,-1070.73 758.233,-1069.86 761.5,-1069 848.98,-1046.04 871.007,-1040.91 958.5,-1018 958.961,-1017.88 959.424,-1017.76 959.889,-1017.64"/>
277
+ <polygon fill="black" stroke="black" stroke-width="0.686813" points="961.008,-1020.96 969.792,-1015.04 959.231,-1014.19 961.008,-1020.96"/>
278
+ <text text-anchor="middle" x="893.5" y="-1039.8" font-family="Times,serif" font-size="14.00">51</text>
279
+ </g>
280
+ <!-- 12405720 -->
281
+ <g id="node42" class="node"><title>12405720</title>
282
+ <polygon fill="none" stroke="black" stroke-width="0.514652" points="1311.5,-1012.5 1137.5,-1012.5 1137.5,-976.5 1311.5,-976.5 1311.5,-1012.5"/>
283
+ <text text-anchor="middle" x="1224.5" y="-998.273" font-family="Times,serif" font-size="11.53">Dry::Logic::Rule::Value#evaluate</text>
284
+ <text text-anchor="end" x="1303.5" y="-985.273" font-family="Times,serif" font-size="11.53">4 (0.7%)</text>
285
+ </g>
286
+ <!-- 12405940&#45;&gt;12405720 -->
287
+ <g id="edge23" class="edge"><title>12405940&#45;&gt;12405720</title>
288
+ <path fill="none" stroke="black" stroke-width="0.514652" d="M751.672,-1071.03C754.983,-1070.31 758.268,-1069.63 761.5,-1069 824.373,-1056.74 841.032,-1059.67 904.5,-1051 1004.2,-1037.38 1029.65,-1036.83 1128.5,-1018 1133.86,-1016.98 1139.37,-1015.86 1144.92,-1014.69"/>
289
+ <polygon fill="black" stroke="black" stroke-width="0.514652" points="1145.88,-1018.07 1154.91,-1012.53 1144.4,-1011.22 1145.88,-1018.07"/>
290
+ <text text-anchor="middle" x="1020" y="-1039.8" font-family="Times,serif" font-size="14.00">4</text>
291
+ </g>
292
+ <!-- 12644760 -->
293
+ <g id="node13" class="node"><title>12644760</title>
294
+ <polygon fill="none" stroke="black" stroke-width="1.29487" points="299,-765 138,-765 138,-715 299,-715 299,-765"/>
295
+ <text text-anchor="middle" x="218.5" y="-750.545" font-family="Times,serif" font-size="13.07">Dry::Logic::Predicate#call</text>
296
+ <text text-anchor="end" x="291" y="-736.545" font-family="Times,serif" font-size="13.07">8 (1.5%)</text>
297
+ <text text-anchor="end" x="291" y="-722.545" font-family="Times,serif" font-size="13.07">of 217 (39.7%)</text>
298
+ </g>
299
+ <!-- 14321700 -->
300
+ <g id="node15" class="node"><title>14321700</title>
301
+ <polygon fill="none" stroke="black" stroke-width="0.961538" points="290.5,-658 146.5,-658 146.5,-614 290.5,-614 290.5,-658"/>
302
+ <text text-anchor="middle" x="218.5" y="-645.386" font-family="Times,serif" font-size="10.77">block in &lt;module:Predicates&gt;</text>
303
+ <text text-anchor="end" x="282.5" y="-633.386" font-family="Times,serif" font-size="10.77">2 (0.4%)</text>
304
+ <text text-anchor="end" x="282.5" y="-621.386" font-family="Times,serif" font-size="10.77">of 126 (23.1%)</text>
305
+ </g>
306
+ <!-- 12644760&#45;&gt;14321700 -->
307
+ <g id="edge24" class="edge"><title>12644760&#45;&gt;14321700</title>
308
+ <path fill="none" stroke="black" stroke-width="0.961538" d="M218.5,-714.827C218.5,-700.985 218.5,-683.457 218.5,-668.541"/>
309
+ <polygon fill="black" stroke="black" stroke-width="0.961538" points="222,-668.231 218.5,-658.231 215,-668.231 222,-668.231"/>
310
+ <text text-anchor="middle" x="229" y="-685.8" font-family="Times,serif" font-size="14.00">126</text>
311
+ </g>
312
+ <!-- 14322200 -->
313
+ <g id="node31" class="node"><title>14322200</title>
314
+ <polygon fill="none" stroke="black" stroke-width="0.613553" points="590,-664 309,-664 309,-608 590,-608 590,-664"/>
315
+ <text text-anchor="middle" x="449.5" y="-642.488" font-family="Times,serif" font-size="21.89">block in &lt;module:Predicates&gt;</text>
316
+ <text text-anchor="end" x="582" y="-618.488" font-family="Times,serif" font-size="21.89">31 (5.7%)</text>
317
+ </g>
318
+ <!-- 12644760&#45;&gt;14322200 -->
319
+ <g id="edge26" class="edge"><title>12644760&#45;&gt;14322200</title>
320
+ <path fill="none" stroke="black" stroke-width="0.613553" d="M272.951,-714.957C304.529,-701.013 344.651,-683.297 378.665,-668.278"/>
321
+ <polygon fill="black" stroke="black" stroke-width="0.613553" points="380.35,-671.36 388.084,-664.119 377.522,-664.956 380.35,-671.36"/>
322
+ <text text-anchor="middle" x="348.5" y="-685.8" font-family="Times,serif" font-size="14.00">31</text>
323
+ </g>
324
+ <!-- 14321880 -->
325
+ <g id="node33" class="node"><title>14321880</title>
326
+ <polygon fill="none" stroke="black" stroke-width="0.595238" points="862.5,-662 608.5,-662 608.5,-610 862.5,-610 862.5,-662"/>
327
+ <text text-anchor="middle" x="735.5" y="-642.022" font-family="Times,serif" font-size="19.97">block in &lt;module:Predicates&gt;</text>
328
+ <text text-anchor="end" x="854.5" y="-620.022" font-family="Times,serif" font-size="19.97">26 (4.8%)</text>
329
+ </g>
330
+ <!-- 12644760&#45;&gt;14321880 -->
331
+ <g id="edge29" class="edge"><title>12644760&#45;&gt;14321880</title>
332
+ <path fill="none" stroke="black" stroke-width="0.595238" d="M299.151,-723.163C376.274,-708.01 495.833,-684.494 599.5,-664 599.603,-663.98 599.707,-663.959 599.81,-663.939"/>
333
+ <polygon fill="black" stroke="black" stroke-width="0.595238" points="600.408,-667.388 609.539,-662.014 599.05,-660.521 600.408,-667.388"/>
334
+ <text text-anchor="middle" x="512.5" y="-685.8" font-family="Times,serif" font-size="14.00">26</text>
335
+ </g>
336
+ <!-- 14318940 -->
337
+ <g id="node35" class="node"><title>14318940</title>
338
+ <polygon fill="none" stroke="black" stroke-width="0.551282" points="1082,-657 881,-657 881,-615 1082,-615 1082,-657"/>
339
+ <text text-anchor="middle" x="981.5" y="-640.704" font-family="Times,serif" font-size="15.37">block in &lt;module:Predicates&gt;</text>
340
+ <text text-anchor="end" x="1074" y="-623.704" font-family="Times,serif" font-size="15.37">14 (2.6%)</text>
341
+ </g>
342
+ <!-- 12644760&#45;&gt;14318940 -->
343
+ <g id="edge25" class="edge"><title>12644760&#45;&gt;14318940</title>
344
+ <path fill="none" stroke="black" stroke-width="0.551282" d="M299.146,-733.037C422.936,-723.142 666.937,-700.701 871.5,-664 879.275,-662.605 887.317,-660.983 895.353,-659.24"/>
345
+ <polygon fill="black" stroke="black" stroke-width="0.551282" points="896.134,-662.652 905.133,-657.06 894.611,-655.82 896.134,-662.652"/>
346
+ <text text-anchor="middle" x="753.5" y="-685.8" font-family="Times,serif" font-size="14.00">14</text>
347
+ </g>
348
+ <!-- 14319880 -->
349
+ <g id="node39" class="node"><title>14319880</title>
350
+ <polygon fill="none" stroke="black" stroke-width="0.525641" points="1270.5,-654 1100.5,-654 1100.5,-618 1270.5,-618 1270.5,-654"/>
351
+ <text text-anchor="middle" x="1185.5" y="-639.852" font-family="Times,serif" font-size="12.68">block in &lt;module:Predicates&gt;</text>
352
+ <text text-anchor="end" x="1262.5" y="-625.852" font-family="Times,serif" font-size="12.68">7 (1.3%)</text>
353
+ </g>
354
+ <!-- 12644760&#45;&gt;14319880 -->
355
+ <g id="edge28" class="edge"><title>12644760&#45;&gt;14319880</title>
356
+ <path fill="none" stroke="black" stroke-width="0.525641" d="M299.01,-737.683C453.863,-733.92 803.385,-719.452 1091.5,-664 1101.61,-662.055 1112.2,-659.516 1122.48,-656.775"/>
357
+ <polygon fill="black" stroke="black" stroke-width="0.525641" points="1123.5,-660.124 1132.22,-654.098 1121.65,-653.375 1123.5,-660.124"/>
358
+ <text text-anchor="middle" x="977" y="-685.8" font-family="Times,serif" font-size="14.00">7</text>
359
+ </g>
360
+ <!-- 14320560 -->
361
+ <g id="node40" class="node"><title>14320560</title>
362
+ <polygon fill="none" stroke="black" stroke-width="0.518315" points="1446.5,-654 1288.5,-654 1288.5,-618 1446.5,-618 1446.5,-654"/>
363
+ <text text-anchor="middle" x="1367.5" y="-639.466" font-family="Times,serif" font-size="11.92">block in &lt;module:Predicates&gt;</text>
364
+ <text text-anchor="end" x="1438.5" y="-626.466" font-family="Times,serif" font-size="11.92">5 (0.9%)</text>
365
+ </g>
366
+ <!-- 12644760&#45;&gt;14320560 -->
367
+ <g id="edge27" class="edge"><title>12644760&#45;&gt;14320560</title>
368
+ <path fill="none" stroke="black" stroke-width="0.518315" d="M299.11,-736.083C438.831,-730.691 734.974,-717.781 984.5,-697 1115.97,-686.051 1150.32,-690.798 1279.5,-664 1288.79,-662.073 1298.51,-659.587 1307.95,-656.905"/>
369
+ <polygon fill="black" stroke="black" stroke-width="0.518315" points="1309.05,-660.23 1317.66,-654.055 1307.08,-653.513 1309.05,-660.23"/>
370
+ <text text-anchor="middle" x="1176" y="-685.8" font-family="Times,serif" font-size="14.00">5</text>
371
+ </g>
372
+ <!-- 12405840&#45;&gt;12644760 -->
373
+ <g id="edge30" class="edge"><title>12405840&#45;&gt;12644760</title>
374
+ <path fill="none" stroke="black" stroke-width="1.02747" d="M394.859,-979.855C330.579,-967.298 248.448,-946.604 227.5,-920 195.075,-878.82 201.425,-814.333 209.56,-775.04"/>
375
+ <polygon fill="black" stroke="black" stroke-width="1.02747" points="213.007,-775.665 211.758,-765.144 206.173,-774.147 213.007,-775.665"/>
376
+ <text text-anchor="middle" x="238" y="-864.3" font-family="Times,serif" font-size="14.00">144</text>
377
+ </g>
378
+ <!-- 12644900 -->
379
+ <g id="node28" class="node"><title>12644900</title>
380
+ <polygon fill="none" stroke="black" stroke-width="0.668498" points="421,-888.5 258,-888.5 258,-847.5 421,-847.5 421,-888.5"/>
381
+ <text text-anchor="middle" x="339.5" y="-876.5" font-family="Times,serif" font-size="10.00">Dry::Logic::Predicate::Curried#call</text>
382
+ <text text-anchor="end" x="413" y="-865.5" font-family="Times,serif" font-size="10.00">0 (0.0%)</text>
383
+ <text text-anchor="end" x="413" y="-854.5" font-family="Times,serif" font-size="10.00">of 46 (8.4%)</text>
384
+ </g>
385
+ <!-- 12405840&#45;&gt;12644900 -->
386
+ <g id="edge31" class="edge"><title>12405840&#45;&gt;12644900</title>
387
+ <path fill="none" stroke="black" stroke-width="0.668498" d="M451.69,-970.954C428.312,-949.709 393.281,-917.874 368.595,-895.441"/>
388
+ <polygon fill="black" stroke="black" stroke-width="0.668498" points="370.727,-892.648 360.972,-888.513 366.019,-897.829 370.727,-892.648"/>
389
+ <text text-anchor="middle" x="435.5" y="-941.8" font-family="Times,serif" font-size="14.00">46</text>
390
+ </g>
391
+ <!-- 14321700&#45;&gt;12644760 -->
392
+ <g id="edge33" class="edge"><title>14321700&#45;&gt;12644760</title>
393
+ <path fill="none" stroke="black" stroke-width="0.598901" d="M232.784,-658.027C238.809,-669.38 243.76,-683.749 240.5,-697 239.799,-699.848 238.868,-702.716 237.783,-705.544"/>
394
+ <polygon fill="black" stroke="black" stroke-width="0.598901" points="234.48,-704.357 233.618,-714.917 240.877,-707.2 234.48,-704.357"/>
395
+ <text text-anchor="middle" x="249.5" y="-685.8" font-family="Times,serif" font-size="14.00">27</text>
396
+ </g>
397
+ <!-- 14637220 -->
398
+ <g id="node19" class="node"><title>14637220</title>
399
+ <polygon fill="none" stroke="black" stroke-width="0.855311" points="279.5,-557 157.5,-557 157.5,-516 279.5,-516 279.5,-557"/>
400
+ <text text-anchor="middle" x="218.5" y="-545" font-family="Times,serif" font-size="10.00">Dry::Container::Mixin#[]</text>
401
+ <text text-anchor="end" x="271.5" y="-534" font-family="Times,serif" font-size="10.00">0 (0.0%)</text>
402
+ <text text-anchor="end" x="271.5" y="-523" font-family="Times,serif" font-size="10.00">of 97 (17.8%)</text>
403
+ </g>
404
+ <!-- 14321700&#45;&gt;14637220 -->
405
+ <g id="edge32" class="edge"><title>14321700&#45;&gt;14637220</title>
406
+ <path fill="none" stroke="black" stroke-width="0.855311" d="M218.5,-613.844C218.5,-600.324 218.5,-582.581 218.5,-567.603"/>
407
+ <polygon fill="black" stroke="black" stroke-width="0.855311" points="222,-567.286 218.5,-557.286 215,-567.286 222,-567.286"/>
408
+ <text text-anchor="middle" x="225.5" y="-578.8" font-family="Times,serif" font-size="14.00">97</text>
409
+ </g>
410
+ <!-- 12122160 -->
411
+ <g id="node20" class="node"><title>12122160</title>
412
+ <polygon fill="none" stroke="black" stroke-width="0.767399" points="895.5,-914 439.5,-914 439.5,-822 895.5,-822 895.5,-914"/>
413
+ <text text-anchor="middle" x="667.5" y="-879.6" font-family="Times,serif" font-size="38.00">Dry::Logic::Result#initialize</text>
414
+ <text text-anchor="end" x="887.5" y="-837.6" font-family="Times,serif" font-size="38.00">73 (13.4%)</text>
415
+ </g>
416
+ <!-- 12123120&#45;&gt;12122160 -->
417
+ <g id="edge35" class="edge"><title>12123120&#45;&gt;12122160</title>
418
+ <path fill="none" stroke="black" stroke-width="0.767399" d="M667.5,-972.38C667.5,-959.166 667.5,-941.477 667.5,-924.471"/>
419
+ <polygon fill="black" stroke="black" stroke-width="0.767399" points="671,-924.016 667.5,-914.016 664,-924.016 671,-924.016"/>
420
+ <text text-anchor="middle" x="674.5" y="-941.8" font-family="Times,serif" font-size="14.00">73</text>
421
+ </g>
422
+ <!-- 12122180 -->
423
+ <g id="node29" class="node"><title>12122180</title>
424
+ <polygon fill="none" stroke="black" stroke-width="0.657509" points="1159,-901 914,-901 914,-835 1159,-835 1159,-901"/>
425
+ <text text-anchor="middle" x="1036.5" y="-875.805" font-family="Times,serif" font-size="26.49">Dry::Logic::Result.[]</text>
426
+ <text text-anchor="end" x="1151" y="-846.805" font-family="Times,serif" font-size="26.49">43 (7.9%)</text>
427
+ </g>
428
+ <!-- 12123120&#45;&gt;12122180 -->
429
+ <g id="edge34" class="edge"><title>12123120&#45;&gt;12122180</title>
430
+ <path fill="none" stroke="black" stroke-width="0.657509" d="M739.737,-972.487C786.9,-958.427 849.672,-939.069 904.5,-920 918.169,-915.246 932.536,-909.98 946.557,-904.688"/>
431
+ <polygon fill="black" stroke="black" stroke-width="0.657509" points="948.09,-907.85 956.195,-901.027 945.604,-901.306 948.09,-907.85"/>
432
+ <text text-anchor="middle" x="852.5" y="-941.8" font-family="Times,serif" font-size="14.00">43</text>
433
+ </g>
434
+ <!-- 12354160 -->
435
+ <g id="node17" class="node"><title>12354160</title>
436
+ <polygon fill="none" stroke="black" stroke-width="0.858974" points="2003,-920 1608,-920 1608,-816 2003,-816 2003,-920"/>
437
+ <text text-anchor="middle" x="1805.5" y="-892.658" font-family="Times,serif" font-size="29.18">Dry::Logic::Evaluator::Key#call</text>
438
+ <text text-anchor="end" x="1995" y="-860.658" font-family="Times,serif" font-size="29.18">50 (9.2%)</text>
439
+ <text text-anchor="end" x="1995" y="-828.658" font-family="Times,serif" font-size="29.18">of 98 (17.9%)</text>
440
+ </g>
441
+ <!-- 12354160&#45;&gt;12354160 -->
442
+ <g id="edge36" class="edge"><title>12354160&#45;&gt;12354160</title>
443
+ <path fill="none" stroke="black" stroke-width="0.675824" d="M2003.24,-877.615C2014.37,-875.287 2021,-872.082 2021,-868 2021,-865.321 2018.14,-863.02 2013.04,-861.097"/>
444
+ <polygon fill="black" stroke="black" stroke-width="0.675824" points="2013.81,-857.68 2003.24,-858.385 2011.95,-864.427 2013.81,-857.68"/>
445
+ <text text-anchor="middle" x="2028" y="-864.3" font-family="Times,serif" font-size="14.00">48</text>
446
+ </g>
447
+ <!-- 14637200 -->
448
+ <g id="node18" class="node"><title>14637200</title>
449
+ <polygon fill="none" stroke="black" stroke-width="0.855311" points="291,-465 146,-465 146,-424 291,-424 291,-465"/>
450
+ <text text-anchor="middle" x="218.5" y="-453" font-family="Times,serif" font-size="10.00">Dry::Container::Mixin#resolve</text>
451
+ <text text-anchor="end" x="283" y="-442" font-family="Times,serif" font-size="10.00">0 (0.0%)</text>
452
+ <text text-anchor="end" x="283" y="-431" font-family="Times,serif" font-size="10.00">of 97 (17.8%)</text>
453
+ </g>
454
+ <!-- 14583000 -->
455
+ <g id="node23" class="node"><title>14583000</title>
456
+ <polygon fill="none" stroke="black" stroke-width="0.723443" points="289,-364.5 148,-364.5 148,-323.5 289,-323.5 289,-364.5"/>
457
+ <text text-anchor="middle" x="218.5" y="-352.5" font-family="Times,serif" font-size="10.00">Dry::Container::Resolver#call</text>
458
+ <text text-anchor="end" x="281" y="-341.5" font-family="Times,serif" font-size="10.00">0 (0.0%)</text>
459
+ <text text-anchor="end" x="281" y="-330.5" font-family="Times,serif" font-size="10.00">of 61 (11.2%)</text>
460
+ </g>
461
+ <!-- 14637200&#45;&gt;14583000 -->
462
+ <g id="edge37" class="edge"><title>14637200&#45;&gt;14583000</title>
463
+ <path fill="none" stroke="black" stroke-width="0.723443" d="M218.5,-423.567C218.5,-409.591 218.5,-390.662 218.5,-374.886"/>
464
+ <polygon fill="black" stroke="black" stroke-width="0.723443" points="222,-374.567 218.5,-364.567 215,-374.567 222,-374.567"/>
465
+ <text text-anchor="middle" x="225.5" y="-394.8" font-family="Times,serif" font-size="14.00">61</text>
466
+ </g>
467
+ <!-- 14637320 -->
468
+ <g id="node30" class="node"><title>14637320</title>
469
+ <polygon fill="none" stroke="black" stroke-width="0.617216" points="556,-373 307,-373 307,-315 556,-315 556,-373"/>
470
+ <text text-anchor="middle" x="431.5" y="-351.181" font-family="Times,serif" font-size="22.27">Dry::Configurable#config</text>
471
+ <text text-anchor="end" x="548" y="-326.181" font-family="Times,serif" font-size="22.27">32 (5.9%)</text>
472
+ </g>
473
+ <!-- 14637200&#45;&gt;14637320 -->
474
+ <g id="edge38" class="edge"><title>14637200&#45;&gt;14637320</title>
475
+ <path fill="none" stroke="black" stroke-width="0.617216" d="M260.837,-423.922C289.559,-410.639 328.208,-392.767 361.462,-377.388"/>
476
+ <polygon fill="black" stroke="black" stroke-width="0.617216" points="363.079,-380.497 370.686,-373.123 360.14,-374.144 363.079,-380.497"/>
477
+ <text text-anchor="middle" x="338.5" y="-394.8" font-family="Times,serif" font-size="14.00">32</text>
478
+ </g>
479
+ <!-- 14637300 -->
480
+ <g id="node43" class="node"><title>14637300</title>
481
+ <polygon fill="none" stroke="black" stroke-width="0.514652" points="749.5,-362 573.5,-362 573.5,-326 749.5,-326 749.5,-362"/>
482
+ <text text-anchor="middle" x="661.5" y="-347.773" font-family="Times,serif" font-size="11.53">Dry::Container::Mixin#_container</text>
483
+ <text text-anchor="end" x="741.5" y="-334.773" font-family="Times,serif" font-size="11.53">4 (0.7%)</text>
484
+ </g>
485
+ <!-- 14637200&#45;&gt;14637300 -->
486
+ <g id="edge39" class="edge"><title>14637200&#45;&gt;14637300</title>
487
+ <path fill="none" stroke="black" stroke-width="0.514652" d="M291.109,-430.456C361.381,-417.42 470.737,-396.046 564.5,-373 574.561,-370.527 585.147,-367.703 595.48,-364.823"/>
488
+ <polygon fill="black" stroke="black" stroke-width="0.514652" points="596.612,-368.14 605.283,-362.053 594.709,-361.404 596.612,-368.14"/>
489
+ <text text-anchor="middle" x="484" y="-394.8" font-family="Times,serif" font-size="14.00">4</text>
490
+ </g>
491
+ <!-- 14637220&#45;&gt;14637200 -->
492
+ <g id="edge40" class="edge"><title>14637220&#45;&gt;14637200</title>
493
+ <path fill="none" stroke="black" stroke-width="0.855311" d="M218.5,-515.971C218.5,-504.141 218.5,-488.809 218.5,-475.468"/>
494
+ <polygon fill="black" stroke="black" stroke-width="0.855311" points="222,-475.301 218.5,-465.301 215,-475.301 222,-475.301"/>
495
+ <text text-anchor="middle" x="225.5" y="-486.8" font-family="Times,serif" font-size="14.00">97</text>
496
+ </g>
497
+ <!-- 12406100 -->
498
+ <g id="node26" class="node"><title>12406100</title>
499
+ <polygon fill="none" stroke="black" stroke-width="0.716117" points="1589.5,-908 1177.5,-908 1177.5,-828 1589.5,-828 1589.5,-908"/>
500
+ <text text-anchor="middle" x="1383.5" y="-877.896" font-family="Times,serif" font-size="32.63">Dry::Logic::Rule::Value#arity</text>
501
+ <text text-anchor="end" x="1581.5" y="-841.896" font-family="Times,serif" font-size="32.63">59 (10.8%)</text>
502
+ </g>
503
+ <!-- 12406140&#45;&gt;12406100 -->
504
+ <g id="edge41" class="edge"><title>12406140&#45;&gt;12406100</title>
505
+ <path fill="none" stroke="black" stroke-width="0.716117" d="M949.659,-972.872C1020.46,-955.92 1123.01,-931.368 1210.62,-910.39"/>
506
+ <polygon fill="black" stroke="black" stroke-width="0.716117" points="1211.5,-913.779 1220.41,-908.047 1209.87,-906.971 1211.5,-913.779"/>
507
+ <text text-anchor="middle" x="1098.5" y="-941.8" font-family="Times,serif" font-size="14.00">59</text>
508
+ </g>
509
+ <!-- 14600200 -->
510
+ <g id="node22" class="node"><title>14600200</title>
511
+ <polygon fill="none" stroke="black" stroke-width="0.723443" points="281.5,-264 155.5,-264 155.5,-223 281.5,-223 281.5,-264"/>
512
+ <text text-anchor="middle" x="218.5" y="-251.693" font-family="Times,serif" font-size="10.38">Dry::Container::Item#call</text>
513
+ <text text-anchor="end" x="273.5" y="-240.693" font-family="Times,serif" font-size="10.38">1 (0.2%)</text>
514
+ <text text-anchor="end" x="273.5" y="-229.693" font-family="Times,serif" font-size="10.38">of 61 (11.2%)</text>
515
+ </g>
516
+ <!-- 12642380 -->
517
+ <g id="node25" class="node"><title>12642380</title>
518
+ <polygon fill="none" stroke="black" stroke-width="0.71978" points="320,-172 117,-172 117,-131 320,-131 320,-172"/>
519
+ <text text-anchor="middle" x="218.5" y="-160" font-family="Times,serif" font-size="10.00">Dry::Logic::PredicateSet::Methods#predicate</text>
520
+ <text text-anchor="end" x="312" y="-149" font-family="Times,serif" font-size="10.00">0 (0.0%)</text>
521
+ <text text-anchor="end" x="312" y="-138" font-family="Times,serif" font-size="10.00">of 60 (11.0%)</text>
522
+ </g>
523
+ <!-- 14600200&#45;&gt;12642380 -->
524
+ <g id="edge42" class="edge"><title>14600200&#45;&gt;12642380</title>
525
+ <path fill="none" stroke="black" stroke-width="0.71978" d="M218.5,-222.971C218.5,-211.141 218.5,-195.809 218.5,-182.468"/>
526
+ <polygon fill="black" stroke="black" stroke-width="0.71978" points="222,-182.301 218.5,-172.301 215,-182.301 222,-182.301"/>
527
+ <text text-anchor="middle" x="225.5" y="-193.8" font-family="Times,serif" font-size="14.00">60</text>
528
+ </g>
529
+ <!-- 14583000&#45;&gt;14600200 -->
530
+ <g id="edge43" class="edge"><title>14583000&#45;&gt;14600200</title>
531
+ <path fill="none" stroke="black" stroke-width="0.723443" d="M218.5,-323.067C218.5,-309.091 218.5,-290.162 218.5,-274.386"/>
532
+ <polygon fill="black" stroke="black" stroke-width="0.723443" points="222,-274.067 218.5,-264.067 215,-274.067 222,-274.067"/>
533
+ <text text-anchor="middle" x="225.5" y="-285.8" font-family="Times,serif" font-size="14.00">61</text>
534
+ </g>
535
+ <!-- 12644820 -->
536
+ <g id="node24" class="node"><title>12644820</title>
537
+ <polygon fill="none" stroke="black" stroke-width="0.71978" points="437,-80 2.84217e-14,-80 2.84217e-14,-0 437,-0 437,-80"/>
538
+ <text text-anchor="middle" x="218.5" y="-49.589" font-family="Times,serif" font-size="33.01">Dry::Logic::Predicate#initialize</text>
539
+ <text text-anchor="end" x="429" y="-13.589" font-family="Times,serif" font-size="33.01">60 (11.0%)</text>
540
+ </g>
541
+ <!-- 12642380&#45;&gt;12644820 -->
542
+ <g id="edge44" class="edge"><title>12642380&#45;&gt;12644820</title>
543
+ <path fill="none" stroke="black" stroke-width="0.71978" d="M218.5,-130.924C218.5,-119.637 218.5,-104.893 218.5,-90.6181"/>
544
+ <polygon fill="black" stroke="black" stroke-width="0.71978" points="222,-90.3628 218.5,-80.3628 215,-90.3628 222,-90.3628"/>
545
+ <text text-anchor="middle" x="225.5" y="-101.8" font-family="Times,serif" font-size="14.00">60</text>
546
+ </g>
547
+ <!-- 12352900&#45;&gt;12354160 -->
548
+ <g id="edge45" class="edge"><title>12352900&#45;&gt;12354160</title>
549
+ <path fill="none" stroke="black" stroke-width="0.68315" d="M1114.28,-973.91C1119.07,-972.847 1123.85,-971.863 1128.5,-971 1331.86,-933.273 1389.79,-955.816 1597.83,-920.048"/>
550
+ <polygon fill="black" stroke="black" stroke-width="0.68315" points="1598.61,-923.467 1607.86,-918.301 1597.4,-916.571 1598.61,-923.467"/>
551
+ <text text-anchor="middle" x="1468.5" y="-941.8" font-family="Times,serif" font-size="14.00">50</text>
552
+ </g>
553
+ <!-- 12644900&#45;&gt;12644760 -->
554
+ <g id="edge46" class="edge"><title>12644900&#45;&gt;12644760</title>
555
+ <path fill="none" stroke="black" stroke-width="0.668498" d="M320.594,-847.312C301.401,-827.327 271.385,-796.07 248.858,-772.612"/>
556
+ <polygon fill="black" stroke="black" stroke-width="0.668498" points="251.281,-770.083 241.83,-765.294 246.232,-774.931 251.281,-770.083"/>
557
+ <text text-anchor="middle" x="279.5" y="-786.8" font-family="Times,serif" font-size="14.00">46</text>
558
+ </g>
559
+ <!-- 17603440&#45;&gt;17603440 -->
560
+ <g id="edge48" class="edge"><title>17603440&#45;&gt;17603440</title>
561
+ <path fill="none" stroke="black" stroke-width="0.540293" d="M986.27,-1299.1C996.93,-1297.63 1004,-1294.77 1004,-1290.5 1004,-1287.77 1001.1,-1285.61 996.21,-1284.03"/>
562
+ <polygon fill="black" stroke="black" stroke-width="0.540293" points="996.78,-1280.57 986.27,-1281.9 995.318,-1287.41 996.78,-1280.57"/>
563
+ <text text-anchor="middle" x="1011" y="-1286.8" font-family="Times,serif" font-size="14.00">11</text>
564
+ </g>
565
+ <!-- 12122040 -->
566
+ <g id="node36" class="node"><title>12122040</title>
567
+ <polygon fill="none" stroke="black" stroke-width="0.540293" points="967,-1213 836,-1213 836,-1172 967,-1172 967,-1213"/>
568
+ <text text-anchor="middle" x="901.5" y="-1201" font-family="Times,serif" font-size="10.00">Dry::Logic::Result#failure?</text>
569
+ <text text-anchor="end" x="959" y="-1190" font-family="Times,serif" font-size="10.00">0 (0.0%)</text>
570
+ <text text-anchor="end" x="959" y="-1179" font-family="Times,serif" font-size="10.00">of 11 (2.0%)</text>
571
+ </g>
572
+ <!-- 17603440&#45;&gt;12122040 -->
573
+ <g id="edge47" class="edge"><title>17603440&#45;&gt;12122040</title>
574
+ <path fill="none" stroke="black" stroke-width="0.540293" d="M904.612,-1268.19C904.06,-1254.95 903.343,-1237.73 902.736,-1223.16"/>
575
+ <polygon fill="black" stroke="black" stroke-width="0.540293" points="906.231,-1222.96 902.317,-1213.11 899.237,-1223.25 906.231,-1222.96"/>
576
+ <text text-anchor="middle" x="910.5" y="-1234.8" font-family="Times,serif" font-size="14.00">11</text>
577
+ </g>
578
+ <!-- 12122040&#45;&gt;12122060 -->
579
+ <g id="edge49" class="edge"><title>12122040&#45;&gt;12122060</title>
580
+ <path fill="none" stroke="black" stroke-width="0.540293" d="M900.878,-1171.71C900.512,-1160.04 900.037,-1144.94 899.609,-1131.29"/>
581
+ <polygon fill="black" stroke="black" stroke-width="0.540293" points="903.105,-1131.11 899.292,-1121.22 896.108,-1131.33 903.105,-1131.11"/>
582
+ <text text-anchor="middle" x="906.5" y="-1142.8" font-family="Times,serif" font-size="14.00">11</text>
583
+ </g>
584
+ <!-- 10194160 -->
585
+ <g id="node38" class="node"><title>10194160</title>
586
+ <polygon fill="none" stroke="black" stroke-width="0.529304" points="1416,-1308.5 1219,-1308.5 1219,-1272.5 1416,-1272.5 1416,-1308.5"/>
587
+ <text text-anchor="middle" x="1317.5" y="-1294.05" font-family="Times,serif" font-size="13.07">Dry::Validation::Result#success?</text>
588
+ <text text-anchor="end" x="1408" y="-1280.05" font-family="Times,serif" font-size="13.07">8 (1.5%)</text>
589
+ </g>
590
+ <!-- 10194360&#45;&gt;10194160 -->
591
+ <g id="edge50" class="edge"><title>10194360&#45;&gt;10194160</title>
592
+ <path fill="none" stroke="black" stroke-width="0.529304" d="M981.046,-1375.41C1055.15,-1356.93 1165.6,-1329.38 1239.52,-1310.95"/>
593
+ <polygon fill="black" stroke="black" stroke-width="0.529304" points="1240.39,-1314.34 1249.24,-1308.52 1238.69,-1307.55 1240.39,-1314.34"/>
594
+ <text text-anchor="middle" x="1138" y="-1338.8" font-family="Times,serif" font-size="14.00">8</text>
595
+ </g>
596
+ <!-- 17785660 -->
597
+ <g id="node44" class="node"><title>17785660</title>
598
+ <polygon fill="none" stroke="black" stroke-width="0.510989" points="1182.5,-1210.5 1054.5,-1210.5 1054.5,-1174.5 1182.5,-1174.5 1182.5,-1210.5"/>
599
+ <text text-anchor="middle" x="1118.5" y="-1195.58" font-family="Times,serif" font-size="11.15">block in &lt;class:Schema&gt;</text>
600
+ <text text-anchor="end" x="1174.5" y="-1183.58" font-family="Times,serif" font-size="11.15">3 (0.5%)</text>
601
+ </g>
602
+ <!-- 17604440&#45;&gt;17785660 -->
603
+ <g id="edge51" class="edge"><title>17604440&#45;&gt;17785660</title>
604
+ <path fill="none" stroke="black" stroke-width="0.510989" d="M1118.5,-1268.19C1118.5,-1254.24 1118.5,-1235.86 1118.5,-1220.83"/>
605
+ <polygon fill="black" stroke="black" stroke-width="0.510989" points="1122,-1220.59 1118.5,-1210.59 1115,-1220.59 1122,-1220.59"/>
606
+ <text text-anchor="middle" x="1122" y="-1234.8" font-family="Times,serif" font-size="14.00">3</text>
607
+ </g>
608
+ </g>
609
+ </svg>
@@ -0,0 +1,148 @@
1
+ require 'allocation_tracer'
2
+
3
+ class Hotch
4
+ def self.memory(name: $0)
5
+ caller = Kernel.caller_locations(1).first
6
+ name = "#{name}:#{caller.path}:#{caller.lineno}"
7
+ memory = Memory.new(name)
8
+
9
+ memory.report_at_exit
10
+ memory.run do
11
+ yield
12
+ end
13
+ end
14
+
15
+ class Memory
16
+ def initialize(name, ignore_paths: [])
17
+ @name = name
18
+ @ignore_paths = Array(ignore_paths || [])
19
+ @report = nil
20
+ @started = nil
21
+ end
22
+
23
+ def start
24
+ ObjectSpace::AllocationTracer.setup [:path, :line, :type]
25
+ ObjectSpace::AllocationTracer.start
26
+ @started = true
27
+ end
28
+
29
+ def stop
30
+ return unless @started
31
+ results = ObjectSpace::AllocationTracer.stop
32
+ @started = nil
33
+ @report = Report.new(results, @ignore_paths)
34
+ end
35
+
36
+ def run
37
+ start
38
+ yield
39
+ ensure
40
+ stop
41
+ end
42
+
43
+ def report
44
+ # TODO make it persistent (as CSV)
45
+ yield @report
46
+ end
47
+
48
+ def report_at_exit
49
+ return if defined? @at_exit_installed
50
+
51
+ at_exit do
52
+ stop
53
+
54
+ report do |report|
55
+ report.puts($stdout)
56
+ end
57
+ end
58
+
59
+ @at_exit_installed = true
60
+ end
61
+
62
+ private
63
+
64
+ def name
65
+ @name.gsub(/\W+/, '_')
66
+ end
67
+
68
+ class Report
69
+ def initialize(results, ignore_paths)
70
+ @header = Line.new(*Line.members)
71
+ @total = Line::Total.new
72
+ @lines = results.map do |result|
73
+ if line = Line.from_result(result, ignore_paths)
74
+ @total.sum(line)
75
+ line
76
+ end
77
+ end.compact
78
+ end
79
+
80
+ def format
81
+ # TODO refactor
82
+ max_lengths = Array.new(Line.members.size, 0)
83
+ ([@header, @total] + @lines).each do |line|
84
+ line.lengths.each.with_index do |length, i|
85
+ max_lengths[i] = length if length > max_lengths[i]
86
+ end
87
+ end
88
+ max_lengths.map { |len| "%#{len}s" }.join(" ")
89
+ end
90
+
91
+ def puts(io)
92
+ fmt = format
93
+ @header.puts(io, fmt)
94
+ @lines.sort_by(&:count).each { |line| line.puts(io, fmt) }
95
+ @total.puts(io, fmt)
96
+ end
97
+
98
+ class Line < Struct.new(:filename, :type, :count, :old_count, :total_age,
99
+ :min_age, :max_age, :total_memsize)
100
+ # [
101
+ # [path, lineno, type],
102
+ # [count, old_count, total_age, min_age, max_age, total_memsize]
103
+ # ]
104
+ def self.from_result(result, ignore_paths)
105
+ path, line, *args = result.flatten(1)
106
+ return if ignore_paths.any? { |ip| ip == path || ip === path }
107
+ filename = "#{strip_path(path)}:#{line}"
108
+ new(filename, *args)
109
+ end
110
+
111
+ def puts(io, fmt)
112
+ send = method(:send)
113
+ io.puts fmt % members.map(&send)
114
+ end
115
+
116
+ def lengths
117
+ members.map { |member| self[member].to_s.size }
118
+ end
119
+
120
+ private
121
+
122
+ MAX_PATH_LENGTH = 50
123
+ def self.strip_path(path)
124
+ strip = %r{#{Regexp.union($LOAD_PATH)}/?}
125
+ path.gsub!(strip, "")
126
+ if path.size > MAX_PATH_LENGTH + 3
127
+ # TODO Refactor
128
+ "..." + path[-MAX_PATH_LENGTH..-1]
129
+ else
130
+ path
131
+ end
132
+ end
133
+
134
+ class Total < Line
135
+ def initialize
136
+ super("TOTAL", "", 0, 0, 0, 0, 0, 0)
137
+ end
138
+
139
+ def sum(other)
140
+ other.to_a.each.with_index do |value, i|
141
+ self[i] += value if Numeric === value
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
@@ -1,3 +1,3 @@
1
1
  class Hotch
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hotch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Suschlik
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-25 00:00:00.000000000 Z
11
+ date: 2016-11-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: stackprof
@@ -16,14 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.2.9
19
+ version: 0.2.10
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.2.9
26
+ version: 0.2.10
27
+ - !ruby/object:Gem::Dependency
28
+ name: allocation_tracer
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.6.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.6.3
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -67,7 +81,10 @@ files:
67
81
  - examples/bundler.rb
68
82
  - examples/simple.rb
69
83
  - hotch.gemspec
84
+ - images/dry-validation.profile_schema_call_valid.png
85
+ - images/dry-validation.profile_schema_call_valid.svg
70
86
  - lib/hotch.rb
87
+ - lib/hotch/memory.rb
71
88
  - lib/hotch/minitest.rb
72
89
  - lib/hotch/run.rb
73
90
  - lib/hotch/version.rb