ObjectSpace::AllocationTracer
This module allows to trace object allocation.
This feature is similar to https://github.com/SamSaffron/memory_profiler and https://github.com/srawlins/allocation_stats. But this feature focused on `age' of objects.
This gem was separated from gc_tracer.gem.
Installation
Add this line to your application's Gemfile:
gem 'allocation_tracer'
And then execute:
$ bundle
Or install it yourself as:
$ gem install allocation_tracer
Usage
Allocation tracing
You can trace allocation and aggregate information. Information includes:
count - how many objects are created.
total_age - total age of objects which created here
max_age - age of longest living object created here
min_age - age of shortest living object created here
Age of Object can be calculated by this formula: [current GC count] - [birth time GC count]
For example:
require 'allocation_tracer'
require 'pp'
pp ObjectSpace::AllocationTracer.trace{
50_000.times{|i|
i.to_s
i.to_s
i.to_s
}
}
will show
{["test.rb", 6]=>[50000, 44290, 0, 6],
["test.rb", 7]=>[50000, 44289, 0, 5],
["test.rb", 8]=>[50000, 44295, 0, 6]}
In this case, 50,000 objects are created at `test.rb:6'. 44,290 is total age of objects created at this line. Average age of object created at this line is 50000/44290 = 0.8858. 0 is minimum age and 6 is maximum age.
You can also specify `type' in GC::Tracer.setup_allocation_tracing() to specify what should be keys to aggregate like that.
require 'allocation_tracer'
require 'pp'
ObjectSpace::AllocationTracer.setup(%i{path line type})
result = ObjectSpace::AllocationTracer.trace do
50_000.times{|i|
a = [i.to_s]
b = {i.to_s => nil}
c = (i.to_s .. i.to_s)
}
end
pp result
and you will get:
{["test.rb", 8, :T_STRING]=>[50000, 49067, 0, 17],
["test.rb", 8, :T_ARRAY]=>[50000, 49053, 0, 17],
["test.rb", 9, :T_STRING]=>[100000, 98146, 0, 17],
["test.rb", 9, :T_HASH]=>[50000, 49111, 0, 17],
["test.rb", 10, :T_STRING]=>[100000, 98267, 0, 17],
["test.rb", 10, :T_STRUCT]=>[50000, 49126, 0, 17]}
Interestingly, you can not see array creations in a middle of block:
require 'allocation_tracer'
require 'pp'
ObjectSpace::AllocationTracer.setup(%i{path line type})
result = ObjectSpace::AllocationTracer.trace do
50_000.times{|i|
[i.to_s]
nil
}
end
pp result
and it prints:
{["test.rb", 8, :T_STRING]=>[50000, 38322, 0, 2]}
There are only string creation. This is because unused array creation is ommitted by optimizer.
Simply you can require `allocation_tracer/trace' to start allocation tracer and output the aggregated information into stdot at the end of program.
require 'allocation_tracer/trace'
# Run your program here
50_000.times{|i|
i.to_s
i.to_s
i.to_s
}
and you will see:
path line count total_age max_age min_age
.../lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb 55 18 23 1 6
.../lib/allocation_tracer/trace.rb 6 2 12 6 6
test.rb 0 1 0 0 0
test.rb 5 50000 41645 0 4
test.rb 6 50000 41648 0 5
test.rb 7 50000 41650 0 5
(tab separated colums)
Lifetime table
You can collect lifetime statistics with ObjectSpace::AllocationTracer.lifetime_table method.
require 'pp'
require 'allocation_tracer'
ObjectSpace::AllocationTracer.lifetime_table_setup true
result = ObjectSpace::AllocationTracer.trace do
100000.times{
Object.new
''
}
end
pp ObjectSpace::AllocationTracer.lifetime_table
will show
{:T_OBJECT=>[3434, 96563, 0, 0, 1, 0, 0, 2],
:T_STRING=>[3435, 96556, 2, 1, 1, 1, 1, 1, 2]}
This output means that the age of 3434 T_OBJECT objects are 0, 96563 objects are 1 and 2 objects are 7. Also the age of 3435 T_STRING objects are 0, 96556 objects are 1 and so on.
Note that these numbers includes living objects and dead objects. For dead objects, age means lifetime. For living objects, age means current age.
Contributing
- Fork it ( http://github.com/
/allocation_tracer/fork ) - Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request
Author
Koichi Sasada from Heroku, Inc.