hotch 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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