allocation_stats 0.1.2 → 0.1.3
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 +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.markdown +6 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +8 -0
- data/TODO +0 -1
- data/allocation_stats.gemspec +5 -3
- data/lib/allocation_stats.rb +14 -6
- data/lib/allocation_stats/allocation.rb +11 -0
- data/lib/allocation_stats/allocations_proxy.rb +17 -2
- data/lib/allocation_stats/core_ext/basic_object.rb +11 -0
- data/spec/allocation_stats/allocations_proxy_spec.rb +17 -1
- data/spec/allocation_stats_spec.rb +2 -2
- data/spec/spec_helper.rb +3 -0
- metadata +10 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1bab6c1d1c04a30dff3888fe15caf0c70dd4b270
|
4
|
+
data.tar.gz: 42e214b270edde7ff0829000f68b79c315837523
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6cd17f62c21a31baec49f1d4e888d3bd05526a544ce77ace63dae4237c61a5d0f0f53195119a6c1ad0b3ac9ed9ae09e1b2519e7acbdbdb51e7406ed633f81feb
|
7
|
+
data.tar.gz: d52980763fdb7a9445b2ac2de36a8dc927aa0da69df5596841d275534acfddc9a85d7bf48f1e29a0a0e25ca8924f795292346b5017c6e31ba2b0de828fbd6faf
|
data/.gitignore
CHANGED
data/CHANGELOG.markdown
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -3,7 +3,9 @@ GEM
|
|
3
3
|
specs:
|
4
4
|
coderay (1.0.9)
|
5
5
|
diff-lcs (1.2.4)
|
6
|
+
docile (1.1.1)
|
6
7
|
method_source (0.8.2)
|
8
|
+
multi_json (1.8.2)
|
7
9
|
pry (0.9.12.2)
|
8
10
|
coderay (~> 1.0.5)
|
9
11
|
method_source (~> 0.8)
|
@@ -16,6 +18,11 @@ GEM
|
|
16
18
|
rspec-expectations (2.13.0)
|
17
19
|
diff-lcs (>= 1.1.3, < 2.0)
|
18
20
|
rspec-mocks (2.13.1)
|
21
|
+
simplecov (0.8.2)
|
22
|
+
docile (~> 1.1.0)
|
23
|
+
multi_json
|
24
|
+
simplecov-html (~> 0.8.0)
|
25
|
+
simplecov-html (0.8.0)
|
19
26
|
slop (3.4.6)
|
20
27
|
yajl-ruby (1.1.0)
|
21
28
|
yard (0.8.7)
|
@@ -26,5 +33,6 @@ PLATFORMS
|
|
26
33
|
DEPENDENCIES
|
27
34
|
pry
|
28
35
|
rspec
|
36
|
+
simplecov
|
29
37
|
yajl-ruby (= 1.1.0)
|
30
38
|
yard
|
data/TODO
CHANGED
data/allocation_stats.gemspec
CHANGED
@@ -3,18 +3,20 @@
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |spec|
|
5
5
|
spec.name = "allocation_stats"
|
6
|
-
spec.version = "0.1.
|
6
|
+
spec.version = "0.1.3"
|
7
7
|
spec.authors = ["Sam Rawlins"]
|
8
8
|
spec.email = ["sam.rawlins@gmail.com"]
|
9
9
|
spec.homepage = "https://github.com/srawlins/allocation_stats"
|
10
10
|
spec.license = "Apache v2"
|
11
11
|
spec.summary = "Tooling for tracing object allocations in Ruby 2.1"
|
12
|
-
spec.description = "Tooling for tracing object allocations in Ruby 2.1"
|
12
|
+
spec.description = "Tooling for tracing object allocations in Ruby 2.1; " +
|
13
|
+
"aggregate information about object allocations; group, " +
|
14
|
+
"sort, and filter allocation information."
|
13
15
|
|
14
16
|
spec.files = `git ls-files`.split("\n")
|
15
17
|
spec.require_paths = ["lib"]
|
16
18
|
|
17
|
-
spec.add_development_dependency "rspec"
|
19
|
+
spec.add_development_dependency "rspec", "< 3"
|
18
20
|
|
19
21
|
# ">= 2.1.0" seems logical, but rubygems thought that "2.1.0.dev.0" did not fit that bill.
|
20
22
|
# "> 2.0.0" was my next guess, but apparently "2.0.0.247" _does_ fit that bill.
|
data/lib/allocation_stats.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
# Licensed under the Apache License, Version 2.0, found in the LICENSE file.
|
3
3
|
|
4
4
|
require "objspace"
|
5
|
+
require_relative "allocation_stats/core_ext/basic_object"
|
5
6
|
require_relative "allocation_stats/allocation"
|
6
7
|
require_relative "allocation_stats/allocations_proxy"
|
7
8
|
|
@@ -38,6 +39,9 @@ class AllocationStats
|
|
38
39
|
|
39
40
|
def initialize(burn: 0)
|
40
41
|
@burn = burn
|
42
|
+
# Copying ridiculous workaround from:
|
43
|
+
# https://github.com/ruby/ruby/commit/7170baa878ac0223f26fcf8c8bf25492415e6eaa
|
44
|
+
Class.name
|
41
45
|
end
|
42
46
|
|
43
47
|
def self.trace(&block)
|
@@ -62,8 +66,8 @@ class AllocationStats
|
|
62
66
|
@existing_object_ids = {}
|
63
67
|
|
64
68
|
ObjectSpace.each_object.to_a.each do |object|
|
65
|
-
@existing_object_ids[object.
|
66
|
-
@existing_object_ids[object.
|
69
|
+
@existing_object_ids[object.__id__ / 1000] ||= []
|
70
|
+
@existing_object_ids[object.__id__ / 1000] << object.__id__
|
67
71
|
end
|
68
72
|
|
69
73
|
ObjectSpace.trace_object_allocations {
|
@@ -77,6 +81,9 @@ class AllocationStats
|
|
77
81
|
return self
|
78
82
|
end
|
79
83
|
|
84
|
+
# Begin tracing object allocations. Tracing must be stopped with
|
85
|
+
# AllocationStats#stop. Garbage collection is disabled while tracing is
|
86
|
+
# enabled.
|
80
87
|
def start
|
81
88
|
GC.start
|
82
89
|
GC.disable
|
@@ -84,8 +91,8 @@ class AllocationStats
|
|
84
91
|
@existing_object_ids = {}
|
85
92
|
|
86
93
|
ObjectSpace.each_object.to_a.each do |object|
|
87
|
-
@existing_object_ids[object.
|
88
|
-
@existing_object_ids[object.
|
94
|
+
@existing_object_ids[object.__id__ / 1000] ||= []
|
95
|
+
@existing_object_ids[object.__id__ / 1000] << object.__id__
|
89
96
|
end
|
90
97
|
|
91
98
|
ObjectSpace.trace_object_allocations_start
|
@@ -98,13 +105,14 @@ class AllocationStats
|
|
98
105
|
ObjectSpace.each_object.to_a.each do |object|
|
99
106
|
next if ObjectSpace.allocation_sourcefile(object).nil?
|
100
107
|
next if ObjectSpace.allocation_sourcefile(object) == __FILE__
|
101
|
-
next if @existing_object_ids[object.
|
102
|
-
@existing_object_ids[object.
|
108
|
+
next if @existing_object_ids[object.__id__ / 1000] &&
|
109
|
+
@existing_object_ids[object.__id__ / 1000].include?(object.__id__)
|
103
110
|
|
104
111
|
@new_allocations << Allocation.new(object)
|
105
112
|
end
|
106
113
|
end
|
107
114
|
|
115
|
+
# Stop tracing object allocations that was started with AllocationStats#start.
|
108
116
|
def stop
|
109
117
|
collect_new_allocations
|
110
118
|
ObjectSpace.trace_object_allocations_stop
|
@@ -4,6 +4,7 @@
|
|
4
4
|
require "json"
|
5
5
|
|
6
6
|
class AllocationStats
|
7
|
+
# Information about an individual allocation is captured in this class.
|
7
8
|
class Allocation
|
8
9
|
# a convenience constants
|
9
10
|
PWD = Dir.pwd
|
@@ -77,6 +78,16 @@ class AllocationStats
|
|
77
78
|
alias_path ? sourcefile_alias : @sourcefile
|
78
79
|
end
|
79
80
|
|
81
|
+
# Returns class name, plus, for Arrays, extended information. When all of
|
82
|
+
# the elements of the Array are instances of a total of three or fewer
|
83
|
+
# classes, then those classes are listed in brackets. For example:
|
84
|
+
#
|
85
|
+
# @example Array with only Fixnum and Bignum elements
|
86
|
+
# allocation.class_plus #=> "Array<Fixnum,Bignum>"
|
87
|
+
# @example Array with elements of class A, B, C, and D
|
88
|
+
# allocation.class_plus #=> "Array"
|
89
|
+
# @example String (not an Array)
|
90
|
+
# allocation.class_plus #=> "String"
|
80
91
|
def class_plus
|
81
92
|
case @object
|
82
93
|
when Array
|
@@ -139,6 +139,15 @@ class AllocationStats
|
|
139
139
|
self
|
140
140
|
end
|
141
141
|
|
142
|
+
# Group allocations by one or more attributes, that is, a list of symbols.
|
143
|
+
# Commonly, you might want to group allocations by:
|
144
|
+
#
|
145
|
+
# * :sourcefile, :sourceline, :class
|
146
|
+
# * :sourcefile, :method_id, :class
|
147
|
+
# * :classpath, :method_id, :class
|
148
|
+
#
|
149
|
+
# In this case, `:class` is the class of the allocated object (as opposed
|
150
|
+
# to `:classpath`, the classpath where the allocation occured).
|
142
151
|
def group_by(*args)
|
143
152
|
@group_keys = args
|
144
153
|
|
@@ -175,9 +184,9 @@ class AllocationStats
|
|
175
184
|
lambda { |allocation| allocation.sourcefile(@alias_paths) }
|
176
185
|
elsif Allocation::HELPERS.include?(faux) ||
|
177
186
|
Allocation::ATTRIBUTES.include?(faux)
|
178
|
-
lambda { |allocation| allocation.
|
187
|
+
lambda { |allocation| allocation.__send__(faux) }
|
179
188
|
else
|
180
|
-
lambda { |allocation| allocation.object.
|
189
|
+
lambda { |allocation| allocation.object.__send__(faux) }
|
181
190
|
end
|
182
191
|
end
|
183
192
|
end
|
@@ -237,6 +246,9 @@ class AllocationStats
|
|
237
246
|
to_a.to_json
|
238
247
|
end
|
239
248
|
|
249
|
+
# Return tabular information about the un-grouped list of Allocations.
|
250
|
+
#
|
251
|
+
# @private
|
240
252
|
def to_text_from_plain(resolved, columns: DEFAULT_COLUMNS)
|
241
253
|
getters = attribute_getters(columns)
|
242
254
|
|
@@ -263,6 +275,9 @@ class AllocationStats
|
|
263
275
|
end
|
264
276
|
private :to_text_from_plain
|
265
277
|
|
278
|
+
# Return tabular information about the grouped Allocations.
|
279
|
+
#
|
280
|
+
# @private
|
266
281
|
def to_text_from_groups(resolved)
|
267
282
|
columns = @group_keys + ["count"]
|
268
283
|
|
@@ -53,6 +53,22 @@ describe AllocationStats::AllocationsProxy do
|
|
53
53
|
results.keys.should include([__FILE__, Array])
|
54
54
|
end
|
55
55
|
|
56
|
+
it "should track new BasicObjects" do
|
57
|
+
class BO < BasicObject; end
|
58
|
+
|
59
|
+
stats = AllocationStats.trace do
|
60
|
+
bo = BO.new
|
61
|
+
end
|
62
|
+
|
63
|
+
results = stats.allocations.group_by(:sourcefile).all
|
64
|
+
expect(results.class).to be(Hash)
|
65
|
+
expect(results.keys.size).to eq(1)
|
66
|
+
expect(results.keys.first).to eq([__FILE__])
|
67
|
+
expect(results[[__FILE__]].class).to eq(Array)
|
68
|
+
expect(results[[__FILE__]].size).to eq(1)
|
69
|
+
expect(results[[__FILE__]].first.object.class).to be(BO)
|
70
|
+
end
|
71
|
+
|
56
72
|
it "should track new objects by path and class_name (Array with 1x type)" do
|
57
73
|
stats = AllocationStats.trace do
|
58
74
|
square_groups = []
|
@@ -312,7 +328,7 @@ describe AllocationStats::AllocationsProxy do
|
|
312
328
|
first = {
|
313
329
|
"file" => "<PWD>/spec/spec_helper.rb",
|
314
330
|
"file (raw)" => "/usr/local/google/home/srawlins/code/allocation_stats/spec/spec_helper.rb",
|
315
|
-
"line" =>
|
331
|
+
"line" => 23,
|
316
332
|
"class_path" => "MyClass",
|
317
333
|
"method_id" => :my_method.to_s,
|
318
334
|
"memsize" => 192,
|
@@ -33,14 +33,14 @@ describe AllocationStats do
|
|
33
33
|
stats.new_allocations.size.should == 1
|
34
34
|
end
|
35
35
|
|
36
|
-
it "should only track new objects; String keys in Hashes
|
36
|
+
it "should only track new objects; String keys in Hashes are frozen" do
|
37
37
|
existing_array = [1,2,3,4,5]
|
38
38
|
|
39
39
|
stats = AllocationStats.trace do
|
40
40
|
new_hash = {"foo" => "bar", "baz" => "quux"}
|
41
41
|
end
|
42
42
|
|
43
|
-
stats.new_allocations.size.should ==
|
43
|
+
stats.new_allocations.size.should == 3
|
44
44
|
end
|
45
45
|
|
46
46
|
it "should only track new objects, using instance method" do
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,30 +1,31 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: allocation_stats
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Rawlins
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-12-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "<"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '3'
|
20
20
|
type: :development
|
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: '
|
27
|
-
description: Tooling for tracing object allocations in Ruby 2.1
|
26
|
+
version: '3'
|
27
|
+
description: Tooling for tracing object allocations in Ruby 2.1; aggregate information
|
28
|
+
about object allocations; group, sort, and filter allocation information.
|
28
29
|
email:
|
29
30
|
- sam.rawlins@gmail.com
|
30
31
|
executables: []
|
@@ -51,6 +52,7 @@ files:
|
|
51
52
|
- lib/allocation_stats.rb
|
52
53
|
- lib/allocation_stats/allocation.rb
|
53
54
|
- lib/allocation_stats/allocations_proxy.rb
|
55
|
+
- lib/allocation_stats/core_ext/basic_object.rb
|
54
56
|
- spec/allocation_stats/allocations_proxy_spec.rb
|
55
57
|
- spec/allocation_stats_spec.rb
|
56
58
|
- spec/spec_helper.rb
|
@@ -74,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
74
76
|
version: '0'
|
75
77
|
requirements: []
|
76
78
|
rubyforge_project:
|
77
|
-
rubygems_version: 2.2.0.
|
79
|
+
rubygems_version: 2.2.0.rc.1
|
78
80
|
signing_key:
|
79
81
|
specification_version: 4
|
80
82
|
summary: Tooling for tracing object allocations in Ruby 2.1
|