allocation_stats 0.1.2 → 0.1.3

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: 58815fef555e954a433a92b7cef4eddd6858569a
4
- data.tar.gz: 6607ada6920ec63153e39418023e77d216eca304
3
+ metadata.gz: 1bab6c1d1c04a30dff3888fe15caf0c70dd4b270
4
+ data.tar.gz: 42e214b270edde7ff0829000f68b79c315837523
5
5
  SHA512:
6
- metadata.gz: 6d4da2e5ad7dc0257b91124fbd506e58dece431047d9e73aee0f20d251c1a462477b1cba0a44c483122be048b2d8b5826d67e83acdf2802174f22e576e622591
7
- data.tar.gz: 52e28c0ba9065822aef3bc575c00c39e1096603b26b610b6df5b912e70e5edd5e17db72bc88c4591f7df9e226201052b2fd42d775ead90ad30ca8c08286384ce
6
+ metadata.gz: 6cd17f62c21a31baec49f1d4e888d3bd05526a544ce77ace63dae4237c61a5d0f0f53195119a6c1ad0b3ac9ed9ae09e1b2519e7acbdbdb51e7406ed633f81feb
7
+ data.tar.gz: d52980763fdb7a9445b2ac2de36a8dc927aa0da69df5596841d275534acfddc9a85d7bf48f1e29a0a0e25ca8924f795292346b5017c6e31ba2b0de828fbd6faf
data/.gitignore CHANGED
@@ -1,2 +1,3 @@
1
+ coverage
1
2
  doc
2
3
  .yardoc
data/CHANGELOG.markdown CHANGED
@@ -1,3 +1,9 @@
1
+ v0.1.3
2
+
3
+ * Fixed: BasicObjects can be tracked; fixes #1
4
+ * Added: much more documentation: up to 83%
5
+ * Fixed: Working with new frozen String keys
6
+
1
7
  v0.1.2
2
8
 
3
9
  * Added: `homepage` in the gemspec
data/Gemfile CHANGED
@@ -9,6 +9,7 @@ end
9
9
 
10
10
  group :test do
11
11
  gem "rspec"
12
+ gem "simplecov", require: false
12
13
  gem "pry"
13
14
 
14
15
  gem "yajl-ruby", "= 1.1.0"
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
@@ -1,3 +1,2 @@
1
- * release first gem version
2
1
  * more in the README
3
2
  * binary
@@ -3,18 +3,20 @@
3
3
 
4
4
  Gem::Specification.new do |spec|
5
5
  spec.name = "allocation_stats"
6
- spec.version = "0.1.2"
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.
@@ -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.object_id / 1000] ||= []
66
- @existing_object_ids[object.object_id / 1000] << object.object_id
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.object_id / 1000] ||= []
88
- @existing_object_ids[object.object_id / 1000] << object.object_id
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.object_id / 1000] &&
102
- @existing_object_ids[object.object_id / 1000].include?(object.object_id)
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.send(faux) }
187
+ lambda { |allocation| allocation.__send__(faux) }
179
188
  else
180
- lambda { |allocation| allocation.object.send(faux) }
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
 
@@ -0,0 +1,11 @@
1
+ # monkey patch to BasicObject, allowing it to respnd to :class
2
+ #
3
+ # @private
4
+ class BasicObject
5
+ # monkey patch to BasicObject, allowing it to respnd to :class
6
+ #
7
+ # @private
8
+ def class
9
+ (class << self; self end).superclass
10
+ end
11
+ end
@@ -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" => 20,
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 count twice :(" do
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 == 7
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
@@ -1,6 +1,9 @@
1
1
  # Copyright 2013 Google Inc. All Rights Reserved.
2
2
  # Licensed under the Apache License, Version 2.0, found in the LICENSE file.
3
3
 
4
+ require "simplecov"
5
+ SimpleCov.start
6
+
4
7
  require_relative "../lib/allocation_stats"
5
8
  require "yaml"
6
9
  require "yajl"
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.2
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-04 00:00:00.000000000 Z
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: '0'
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: '0'
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.preview.1
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