Object lifetime analysis with Ruby 2.1
Koichi Sasada<[email protected]>
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
1
Who am I ?
• Koichi Sasada a.k.a. ko1
• From Japan
• 笹田 (family name) 耕一 (given name) in Kanji character
2Object lifetime analysis with Ruby 2.1,
RubyConf.tw 2014, K.Sasada from Heroku, Inc.
Who am I ?
•CRuby/MRI committer• Virtual machine (YARV) from Ruby 1.9
• YARV development since 2004/1/1
• Recently, improving GC performance
• Matz team at Heroku, Inc.• Full-time CRuby developer
• Working in Japan
• Director of Ruby Association
3Object lifetime analysis with Ruby 2.1,
RubyConf.tw 2014, K.Sasada from Heroku, Inc.
• Foundation to encourage Ruby dev. and communities• Chairman is Matz, Located at Matsue-city, Shimane, Japan
• Activities• Ruby programmer certification program
• http://www.ruby.or.jp/en/certification/examination/ in English
• Maintenance of Ruby (Cruby) interpreter• Now, it is for Ruby 1.9.3• Ruby 2.0.0 in the future?
• Events, especially RubyWorld Conference• Ruby Prize• Grant project. We have selected 3 proposals in 2013
• Win32Utils Support, Conductor, Smalruby - smalruby-editor• We will make this grant 2014!!
• Donation for Ruby developments and communities
Advertisement
4Object lifetime analysis with Ruby 2.1,
RubyConf.tw 2014, K.Sasada from Heroku, Inc.
• Heroku, Inc. http://www.heroku.com
You should know about Heroku!!
Advertisement
5Object lifetime analysis with Ruby 2.1,
RubyConf.tw 2014, K.Sasada from Heroku, Inc.
This presentation is supported by
6Object lifetime analysis with Ruby 2.1,
RubyConf.tw 2014, K.Sasada from Heroku, Inc.
Advertisement
• Heroku, Inc. http://www.heroku.com
• Heroku supports OSSs / Ruby development• Many talents for Ruby, and also other languages
• Heroku employs 3 Ruby interpreter core developers• Matz
• Nobu
• Ko1 (me)
• We name our group “Matz team”
Advertisement
7Object lifetime analysis with Ruby 2.1,
RubyConf.tw 2014, K.Sasada from Heroku, Inc.
Matz team in Herokuin Japan
8
Matz @ ShimaneTitle collector
Nobu @ TochigiPatch monster
ko1 @ TokyoEDD developer
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
Mission of Matz team
• Improve quality of next version of CRuby• Matz decides a spec finally
• Nobu fixed huge number of bugs
• Ko1 improves the performance
Current target is Ruby 2.2!!Now, Ruby 2.1 is old version for us.
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
9
Ruby 2.1Current stable
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
10
http://www.flickr.com/photos/loginesta/5266114104
Ruby 2.1
• Ruby 2.1.0 was released at 2013/12/25• New features
• Performance improvements
• Ruby 2.1.1 was released at 2014/02/24• Includes many bug fixes found after 2.1.0 release
• Introduce a new GC tuning parameter to change generational GC behavior (introduce it later)
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
11
Ruby 2.1 the biggest change Version policy• Change the versioning policy
• Drop “patch level” in the version
• Teeny represents patch level• Release new teeny versions about every 3 month
• Teeny upgrades keep compatibility
• Minor upgrades can break backward compatibility• We make an effort to keep compatibility
(recently. Remember Ruby 1.9 )
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
12
Ruby 2.1 New syntax
•New syntaxes• Required keyword
parameter• Rational number literal• Complex number literal• `def’ returns symbol of
method name
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
13
http://www.flickr.com/photos/rooreynolds/4133549889
Ruby 2.1 Runtime new features
• String#scrub
• Process.clock_gettime
• Binding#local_variable_get/set
• Bignum now uses GMP (if available)
• Extending ObjectSpace
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
14
Performance improvements
• Optimize “string literal”.freeze
• Sophisticated inline method cache
• Introducing Generational GC: RGenGC
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
15
0
2
4
6
8
10
12
14
Total mark time (ms) Total sweep time (sec)
Acc
um
ula
ted
exe
cuti
on
tim
e (
sec)
w/o RGenGC RGenGC
RGenGCPerformance evaluation (RDoc)
16
About x15 speedup!
* Disabled lazy sweep to measure correctly.Object lifetime analysis with Ruby 2.1,
RubyConf.tw 2014, K.Sasada from Heroku, Inc.
RGenGCPerformance evaluation (RDoc)
17
* 12% improvements compare with w/ and w/o RGenGC* Disabled lazy sweep to measure correctly.
103.7627479 102.3799865
16.043938154.946003494
0
20
40
60
80
100
120
140
w/o RGenGC RGenGC
Tota
l exe
cuti
on
tim
e (s
ec)
other than GC GC
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
Ruby 2.2Next version
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
18
http://www.flickr.com/photos/adafruit/8483990604
Schedule of Ruby 2.2
• Not published officially
• Schedule draft is available by Naruse-san• https://bugs.ruby-lang.org/projects/ruby-
trunk/wiki/ReleaseEngineering22
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
19
Ruby 2.2 schedule
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
20
2014/12/25Ruby 2.2.0
RubyKaigi9/18, 19, 20
RubyConf11/17, 18, 19Rubyconf.tw
4/25, 26
Rubyconf.PH3/28, 29
We are here!2013/12
Ruby 2.1.0
RDRC6/26, 27
Events are important forEDD (Event Driven Development) Developers
Ruby 2.2 (rough) schedule
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
21
2014/12/25Ruby 2.2.0
2013/12Ruby 2.1.0
Sep/2014Preview 1
Big feature freeze
Nov/2014Preview2
Feature freeze
Dec/2014Release
candidate
Bug fix only
Critical Bug fix only
We are here!
2.2 big features (planned)
• New syntax: not available now
• New method: not available now
• Internal• GC
• Symbol GC (merged recently)
• 2age promotion strategy for RGenGC
• Incremental GC to reduce major GC pause time
• VM• More sophisticated method cache
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
22
Symbol GC
• Symbols remain forever → Security issue• “n.times{|i| i.to_s.to_sym}”
creates “n” symbols and they are never collected
• Symbol GC: Collect dynamically created symbols
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
23
Object lifetime
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
24
Ruby’s object/memory management• “Object.new” allocate a new object
• “foo” (string literal) also allocate a new object
• Everything are objects in Ruby!
• We don’t need to “de-allocate” objects manually
Why we don’t need to clean up objects?
Memory management tuning in Ruby, RubyConfPH 2014 by K.Sasada
http://www.flickr.com/photos/circasassy/6817999189/
Garbage collectionThe automatic memory management
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
26
Garbage collectionThe automatic memory management
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
27
Garbage collectionThe automatic memory management
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
28
Object lifetime
• Human’s lifetime
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
29
Birth DeathLifetime
Birth Death
Object lifetime
# Object creationobj = Object.new
# Collected by GC# when nobody refers it
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
30
Birth Death
Object lifetime
GC surviving count→ Age
GC GC GC
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
31
Age at the dying→ Lifetime
Why lifetime is important?
• Old objects slow down major (full) GC• RGenGC have reduced GC overhead comes from
old objects• However, major (full) GC needs a time
• Long life (old) objects can be unexpected memory leak
Reducing old objects makesRuby program faster
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
32
Questions
•How to measure object lifetime?
•How to find old objects?
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
33
Allocation tracer gem
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
34
Allocation tracer
•Trace object allocations• Two features
1. Show statistics data by line2. Show lifetime statistics table
• Using newobj/freeobj internal hooks introduced from Ruby 2.1.0.
• So that this gem only supports Ruby 2.1 and later
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
35
Allocation Tracer(1) Show statistics data by line• Show statistics data by each lines
• Collect following data• Allocation count
• Old object count
• Total object lifetime (average lifetime by dividing allocation count)
• Min/Max lifetime
• Total amount of memory usage (average memory usage by dividing allocation count)
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
36
Allocation Tracer(1) Show statistics data by lineDemo
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
37
Allocation Tracer(2) Object lifetime statistics• Show object lifetime statistics table for each type
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
38
Age 0 1 2 3 4 5 6 7 8 9 10T_OBJECT 7534 435532 6695 12916 2841 2298 2570 4222 3256 2659 4839
T_CLASS 0 90 1 0 0 0 0 0 4 5 1
T_STRING 116307 17706739 24244 97981 9461 5470 4825 7243 6533 5581 15826
T_REGEXP 0 41192 1 0 0 0 0 0 0 3 0
T_ARRAY 32874 4490228 5878 9262 4863 2567 2485 5697 3752 3033 5672
T_HASH 872 89158 113 323 90 85 93 138 161 101 183
T_STRUCT 1 8507 247 197 62 55 59 9 42 67 127
T_FILE 1 9330 5 2 1 1 0 0 0 0 0
T_DATA 8510 578913 146 69 96 53 77 54 65 90 62
T_MATCH 7 829992 52 0 0 0 0 0 0 0 0
T_RATIONAL
0 2 0 0 0 0 0 0 0 0 0
T_NODE 9333 649080 19438 4948 2665 7 17 5 9 26 135
T_ICLASS 0 90 1 0 0 0 0 0 0 1 1
T_MODULE
0 0 0 0 0 0 0 0 0 0 0
T_FLOAT 0 0 0 0 0 0 0 0 0 0 0
Allocation Tracer(2) Object lifetime statistics• Show object lifetime table for each type
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
39
0
2000000
4000000
6000000
8000000
10000000
12000000
14000000
16000000
18000000
20000000
1 5 9
13
17
21
25
29
33
37
41
45
49
53
57
61
65
69
73
77
81
85
89
93
97
10
1
10
5
10
9
11
3
11
7
12
1
12
5
12
9
13
3
13
7
14
1
14
5
14
9
15
3
15
7
16
1
16
5
16
9
17
3
17
7
18
1
18
5
18
9
Ob
ject
co
un
t
Object lifetime
T_OBJECT T_CLASS T_STRING T_REGEXP T_ARRAY T_HASH T_STRUCT T_FILE
T_DATA T_MATCH T_RATIONAL T_NODE T_ICLASS T_MODULE T_FLOAT
Allocation Tracer(2) Object lifetime statistics• Show object lifetime table for each type
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
40
0
0.2
0.4
0.6
0.8
1
1.2
1 5 9
13
17
21
25
29
33
37
41
45
49
53
57
61
65
69
73
77
81
85
89
93
97
10
1
10
5
10
9
11
3
11
7
12
1
12
5
12
9
13
3
13
7
14
1
14
5
14
9
15
3
15
7
16
1
16
5
16
9
17
3
17
7
18
1
18
5
18
9
Per
cen
tage
of
ob
ject
s
Object lifetime
Age/percentage
T_OBJECT T_CLASS T_STRING T_REGEXP T_ARRAY T_HASH T_STRUCT T_FILE
T_DATA T_MATCH T_RATIONAL T_NODE T_ICLASS T_MODULE T_FLOAT
Allocation Tracer(2) Object lifetime statistics
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
41
T_STRING69%
T_ARRAY18%
T_OBJECT4%
T_MATCH3%
T_NODE3%
T_DATA2%
T_HASH1%
T_REGEXP0%
T_STRUCT0%
T_FILE0%
T_CLASS0%
T_ICLASS0%
T_MODULE0%
T_FLOAT0%
T_RATIONAL0%
Most of allocated objects are String
Allocation Tracer demo(2) Object lifetime statistics
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
42
T_STRING
Most of String die at first GC
Allocation Tracer example
• Using “by line” statistics on RDoc program
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
43
Allocation Tracer example
path line counttotal_memsize
/home/ko1/src/ruby/trunk/lib/rdoc/markup/parser.rb
327 128,097 498,086,366
/home/ko1/src/ruby/trunk/lib/rdoc/parser/c.rb 644 3,132 111,437,037
/home/ko1/src/ruby/trunk/lib/time.rb 325 1,146,900 85,714,539
/home/ko1/src/ruby/trunk/lib/rdoc/token_stream.rb
59 1,267,168 81,137,600
/home/ko1/src/ruby/trunk/lib/rdoc/store.rb 892 23,038 65,504,272
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
44
lib/rdoc/markup/parser.rb:327
@input.byteslice(0, byte_offset).length
• @input is String
• @input.byteslice(0, byte_offset) makes new String
• Return only length of sliced string
→ Created string object is completely temporary
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
45
lib/rdoc/markup/parser.rb:327
Introduce String#byteslice_length
@input.byteslice_length(0, byte_offset)
• No temporary String object
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
46
After introducing new method…
path line count total_memsize/home/ko1/src/ruby/trunk/lib/rdoc/parser/c.rb
644 4,369 93,019,334
/home/ko1/src/ruby/trunk/lib/rdoc/token_stream.rb
59 1,386,966 88,834,304
/home/ko1/src/ruby/trunk/lib/time.rb
325 1,137,612 84,959,225
/home/ko1/src/ruby/trunk/lib/rdoc/ruby_lex.rb
162 944,833 60,724,300
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
47
And total consuming memory reduced fromabout 140MB to 120MB
Another GC tipGC Tracer
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
48
gc_tracer gem
• Helper gem to analyze GC behavior for tuning
http://www.flickr.com/photos/nasa_goddard/5188180370
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
49
How to use tuning parameters?
1. Profile your application
2. Try GC parameters (environment variables)
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
50
Profile memory managementGC.stat (MRI specific)• “GC.stat” returns statistics information about GC
• Counts• :count=>2, # GC count• :minor_gc_count=>2, # minor GC count• :major_gc_count=>0, # major GC count
• Current slot information• :heap_live_slot=>6836, #=> # of live objects• :heap_free_slot=>519, #=> # of freed objects• :heap_final_slot=>0, #=> # of waiting finalizer objects• total_slots = heap_live_slot + heap_free_slot + heap_final_slot
• Statistics• :total_allocated_object=>7674, # total allocated objects• :total_freed_object=>838, # total freed objects• Current living objects = total_allocated_object - total_freed_object
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
51
Profile memory managementGC.latest_gc_info (MRI specific)• “GC.latest_gc_info” returns details of latest GC
• :gc_by=>:newobj # why GC invoked?• newobj: no slots available
• malloc: malloc_increase > malloc_limit
• :major_by=>nil # why major GC invoked?
• :have_finalizer=>false # have finalizer?
• :immediate_sweep=>false # immediate sweep?
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
52
Profile memory management“gc_tracer” gem (MRI 2.1.0 later!!)
• GC::Tracer.start_logging(filename)• Save all GC.stat/GC.latest_gc_info results at every GC events
into specified file
• GC events:• Start
• End marking
• End sweeping
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
53
Sweep Sweep
GC start
GC end marking
GC end sweepingMark Sweep Sweep
GC start
GC end marking
GC end sweepingMark
Profile memory management“gc_tracer” gem• Run your application with gc_tracer
• Plot with Excel!
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
54
http://www.flickr.com/photos/microsoftsweden/5394685465
Profile memory management“gc_tracer” gem
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
55
0
20
40
60
80
100
120
1 7
13
19
25
31
37
43
49
55
61
67
73
79
85
91
97
10
3
10
9
11
5
12
1
12
7
13
3
13
9
14
5
15
1
15
7
16
3
16
9
17
5
18
1
18
7
19
3
19
9
20
5
21
1
21
7
22
3
22
9
23
5
24
1
24
7
25
3
25
9
26
5
27
1
27
7
minor_gc_count major_gc_count
Profile memory management“gc_tracer” gem
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
56
0
5,000,000
10,000,000
15,000,000
20,000,000
25,000,000
30,000,000
35,000,000
40,000,000
1 7
13
19
25
31
37
43
49
55
61
67
73
79
85
91
97
10
3
10
9
11
5
12
1
12
7
13
3
13
9
14
5
15
1
15
7
16
3
16
9
17
5
18
1
18
7
19
3
19
9
20
5
21
1
21
7
22
3
22
9
23
5
24
1
24
7
25
3
25
9
26
5
27
1
27
7
total_allocated_object total_freed_object
Profile memory management“gc_tracer” gem
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
57
0
100,000
200,000
300,000
400,000
500,000
600,000
700,000
800,000
900,000
1,000,000
1 7
13
19
25
31
37
43
49
55
61
67
73
79
85
91
97
10
3
10
9
11
5
12
1
12
7
13
3
13
9
14
5
15
1
15
7
16
3
16
9
17
5
18
1
18
7
19
3
19
9
20
5
21
1
21
7
22
3
22
9
23
5
24
1
24
7
25
3
25
9
26
5
27
1
27
7
total_slots heap_swept_slot
Profile memory management“gc_tracer” gem
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
58
0
200000
400000
600000
800000
1000000
1200000
1400000
1600000
1 7
13
19
25
31
37
43
49
55
61
67
73
79
85
91
97
10
3
10
9
11
5
12
1
12
7
13
3
13
9
14
5
15
1
15
7
16
3
16
9
17
5
18
1
18
7
19
3
19
9
20
5
21
1
21
7
22
3
22
9
23
5
24
1
24
7
25
3
25
9
26
5
ruby 2.2 dev/RUBY_GC_HEAP_OLDOBJECT_FACTOR=2.0 (default)
total_slots old_object old_object_limit
Profile memory management“gc_tracer” gem
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
59
0
100000
200000
300000
400000
500000
600000
700000
800000
900000
1000000
1 7
13
19
25
31
37
43
49
55
61
67
73
79
85
91
97
10
3
10
9
11
5
12
1
12
7
13
3
13
9
14
5
15
1
15
7
16
3
16
9
17
5
18
1
18
7
19
3
19
9
20
5
21
1
21
7
22
3
22
9
23
5
24
1
24
7
25
3
25
9
26
5
27
1
27
7
Ruby 2.2dev w/ RUBY_GC_HEAP_OLDOBJECT_FACTOR=1.3
total_slots old_object old_object_limit
For more information
Please refer my slide at RubyConf PH 2014
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
60
Summary of this talk
• Ruby 2.1 was released and 2.2 will be released this year
• Object lifetime analysis is important for program tuning
• Allocation Tracer gem helps how applications allocate objects
• Another GC Tips• GC Tracer gem helps GC behavior analysis for GC tuning
Object lifetime analysis with Ruby 2.1, RubyConf.tw 2014, K.Sasada from Heroku, Inc.
61
Thank you for your attentionQ&A?
Koichi Sasada<[email protected]>
62Object lifetime analysis with Ruby 2.1,
RubyConf.tw 2014, K.Sasada from Heroku, Inc.