Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2...

68
Evolution of Keyword parameters Koichi Sasada <[email protected]> Rubyconf Portugal’15

Transcript of Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2...

Page 1: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Evolution of Keyword parameters

Koichi Sasada<[email protected]>

Rubyconf Portugal’15

Page 2: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Background“Keyword parameters” from Ruby 2.0

# From Ruby 2.0 feature

def foo(k1: 1, k2: 2)

p [k1, k2] #=> [345, 2]

end

foo(k1: 345)

Page 3: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Background“Keyword parameters” was slow!!

02468

10121416

foo6(1, 2, 3, 4, 5, 6) foo_kw6(k1: 1, k2: 2, k3: 3, k4: 4,k5: 5, k6: 6)

Exec

uti

on

tim

e (s

ec)

Repeat 10M times

Evaluation on Ruby 2.1

x30 slower

Page 4: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

SummaryRuby 2.2 optimized

“keyword parameters”

0

5

10

15

20

foo6(1, 2, 3, 4, 5, 6) foo_kw6(k1: 1, k2: 2, k3: 3, k4: 4,k5: 5, k6: 6)

Exec

uti

on

tim

e (s

ec)

Repeat 10M times

Ruby 2.1 Ruby 2.2

x14 faster!!

But still x2 times slower compare with normal dispatch

Page 5: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Why was slow?

How to solve it?

Page 6: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Koichi Sasada is a Programmer

•MRI committer since 2007/01•Original YARV developer since

2004/01• YARV: Yet Another RubyVM• Introduced into Ruby (MRI) 1.9.0 and

later

•Generational/incremental GC for 2.x

Page 7: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Koichi Sasada from Japan

English Thank you

Portuguese Obrigado

Japanese Arigatoありがとう

Japanese lesson

Page 8: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Koichi is an Employee

Page 9: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Koichi is a member of Heroku Matz team

Mission

Design Ruby language

and improve quality of MRI

Heroku employs three full time Ruby core developers in Japan named “Matz team”

Page 10: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Heroku Matz team

Matz Designer/director of Ruby

NobuQuite active committer

Ko1Internal Hacker

Page 11: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

MatzTitle collector

• He has so many (job) title• Chairman - Ruby Association

• Fellow - NaCl

• Chief architect, Ruby - Heroku

• Research institute fellow – Rakuten

• Chairman – NPO mruby Forum

• Senior researcher – Kadokawa Ascii Research Lab

• Visiting professor – Shimane University

• Honorable citizen (living) – Matsue city

• Honorable member – Nihon Ruby no Kai

• …

• This margin is too narrow to contain

Page 12: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

NobuGreat Patch monster

Ruby’s bug

|> Fix Ruby

|> Break Ruby

|> And Fix Ruby

Page 13: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

NobuPatch monster

nobu29%

akr12%svn

9%naruse

8%usa4%

ko14%

drbrain3%

kosaki3%

kazu2%

zzak2%

tenderlove2%

matz2%

marcandre2%

mame2%

tadf2%

knu1%

shugo1%

nagachika1%

yugui1%

kou1%

mrkn1%

emboss1%

shyouhei1%

nari0%

glass0%

ktsj0%

nahi0%

ayumin0%

tarui0%

sorah0%ryan0%

charliesome

0%

shirosaki0%xibbar

0%nagai

0%eregon

0%ngoto

0%wanabe

0%azav0%

keiju0%suke0%

kouji0%

duerst0%

takano320%

luislavena0%jeg20%hsbt0%

arton0%seki0%

kanemoto0%

tmm10%

eban0%

muraken0%

headius0%

evan0%

a_matsuda0%

iwamatsu0%

technorama

0%

davidflanagan0%

gotoken0%

okkez0%

COMMIT RATIO IN LAST 5 YEARS

Commit count of MRI

Page 14: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

NobuThe Ruby Hero

Page 15: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Ko1EDD developer

0

5

10

15

20

25

20

10

/11

/8

20

11

/1/8

20

11

/3/8

20

11

/5/8

20

11

/7/8

20

11

/9/8

20

11

/11

/8

20

12

/1/8

20

12

/3/8

20

12

/5/8

20

12

/7/8

20

12

/9/8

20

12

/11

/8

20

13

/1/8

20

13

/3/8

20

13

/5/8

20

13

/7/8

20

13

/9/8

20

13

/11

/8

Commit number of ko1 (last 3 years)

RubyConf2012

RubyKaigi2013

Ruby 2.0

Euruko2013

RubyConf2013

EDD: Event Driven Development

Page 16: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Heroku Matz team and Ruby core teamRecent achievement

Ruby 2.2Current stable

Page 17: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Ruby 2.2Syntax

• Symbol key of Hash literal can be quoted

{“foo-bar”: baz}#=> {:“foo-bar” => baz}#=> not {“foo-bar” => baz} like JSON

TRAP!!Easy to misunderstand

(I wrote a wrong code, already…)

Page 18: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Ruby 2.2Classes and Methods• Some methods are introduced• Kernel#itself• String#unicode_normalize• Method#curry• Binding#receiver• Enumerable#slice_after, slice_before• File.birthtime• Etc.nprocessors• …

Page 19: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Ruby 2.2Improvements

• Improve GC• Symbol GC• Incremental GC• Improved promotion algorithm

• Young objects promote after 4 GCs

• Fast keyword parameters

•Use frozen string literals if possible

Page 20: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Ruby 2.2Symbol GCbefore = Symbol.all_symbols.size

1_000_000.times{|i| i.to_s.to_sym} # Make 1M symbols

after = Symbol.all_symbols.size; p [before, after]

# Ruby 2.1

#=> [2_378, 1_002_378] # not GCed# Ruby 2.2

#=> [2_456, 2_456] # GCed!

Page 21: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Ruby 2.2Symbol GC Issues history• Ruby 2.2.0 has memory (object) leak problem

• Symbols has corresponding String objects• Symbols are collected, but Strings are not collected!

(leak)

• Ruby 2.2.1 solved this problem!!• However, 2.2.1 also has problem (rarely you encounter

BUG at the end of process [Bug #10933] ← not big issue, I want to believe)

• Ruby 2.2.2 had solved [Bug #10933]!!• However, patch was forgot to introduce!!

• Finally, Ruby 2.2.3 solved it!!• Please use newest version!!

Page 22: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Ruby 2.2Incremental GC

BeforeRuby 2.1

Ruby 2.1 RGenGC

Incremental GC

Ruby 2.2 Gen+IncGC

Throughput Low High Low High

Pause time Long Long Short Short

Goal

Page 23: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

RGenGC from Ruby 2.1:Micro-benchmark

1699.805974

87.230735

704.843669

867.740319

0

500

1000

1500

2000

2500

3000

no RGenGC

Tim

e (m

s)

total mark total sweep

x2.5 faster

Page 24: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

RGenGC from Ruby 2.1:Pause time

Most of cases, FASTER

(w/o rgengc)

Page 25: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

RGenGC from Ruby 2.1:Pause time

Several peaks

(w/o rgengc)

Page 26: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Ruby 2.2 Incremental GC

Short pause time

Page 27: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Heroku Matz team and Ruby core teamNext target is

Ruby 2.3

Page 28: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Heroku Matz team and Ruby core teamNext target is

Ruby 2.3No time to talk about it.

Please ask me later

Page 29: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Back to the main topic

Page 30: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Ruby has many

Let’s play hangman game

Page 31: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Ruby has many

Page 32: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Ruby has many

Page 33: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Ruby has many

Page 34: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

RubyConf 2008 Keynoteby Dave Thomas (Pragmatic programmer)

Quoted from Dave Thomas Keynote

Page 35: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

RubyConf 2008Keynote by Dave Thomas

Quoted from Dave Thomas Keynote

Page 36: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

RubyConf 2008Keynote by Dave Thomas

Quoted from Dave Thomas Keynote

Page 37: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Ruby has many

RubyConf Portgual 2015Koichi Sasada

Page 38: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Ruby has many

Or Methods

Page 39: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Optimizing Func(tion)s or Methods is important for Ruby

• Syntax optimization (readable/writable)• Call without parenthesis• Passing blocks with braces or do/end• Splat/block arguments (*args, &block)• Optional/rest/post/block parameters by def

• def foo(m1, m2, o1=1, o2=2, *rest, p1, p2, &block)

• Keyword arguments/parameters

•Performance optimization• By virtual machine implementation. My task

Page 40: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Tough work to pass many arguments

# Quoted from my Ruby code

scinsn = Instruction.new(

name, opes, pops, rets, comm,

orig_insn.body, orig_insn.tvars, orig_insn.sp_inc,

orig_insn, orig_insn.defopes, :sc, nextsc, pushs)

12 arguments.Can’t understand what parameter mean.

Page 41: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Tough work to pass many arguments

# Difficult to understand what we specify

GC::Tracer.start_logging(filename, false, false, false)

Only 4 arugments, but also it’s difficult to read

Page 42: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Keyword parameter helps you

# quoted from my Ruby code

GC::Tracer.start_logging(

filename,

gc_stat: false,

gc_latest_gc_info: false,

rusage: false

) Easy to understand!

Page 43: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

The History ofKeyword parameter

Page 44: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Hash notation at the last argumentfrom beginning of Ruby

foo(1, 2, :key1 => v1, :key2 => v2 )

# Same as

# foo(1, 2, {:key1 => v1, :key2 => v2})

Create a Hash object

3 arguments

Page 45: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Symbol hash notationfrom Ruby 1.9.3

foo(1, 2, key1: v1, key2: v2)

# Same as

# foo(1, 2, :key1 => v1, :key2 => v2)

# foo(1, 2, {:key1 => v1, :key2 => v2})

Page 46: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Keyword parameters processing before Ruby 2.0

def foo(a, b, kw={}) # kw is Hash

key1 = kw.fetch(:key1, 1)

key2 = kw.fetch(:key2, 2)

# check unknown kws

endDefault values

Page 47: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Keyword parametersfrom Ruby 2.0 (1)

def foo(a, b, key1: 1, key2: 2)

endDefault values

(any Ruby’s expression)

We don’t need to writeHash access any more!

Page 48: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Keyword parametersfrom Ruby 2.0 (2)

• Raise an exception when unknown keywords are passed

• Rest keyword parameter (**kw) can receive non-specified keyword parameters

def foo(k1: v1, **kw)

p kw #=> {k2: 2, k3: 3}

end

foo(k1: 1, k2: 2, k3: 3)

• Blocks also can accept keyword parameters

foo{|k1: 1, k2: 2| …}

Page 49: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Required keyword parameter from Ruby 2.1

def foo(a, b, key1: 1, key2:)

end

# Similar to

def foo(a, b, key1: 1, key2: raise(“err”))

end

No default valueNeed to specify by caller

Page 50: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

The Implementation ofKeyword parameter

Page 51: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Implementation of keyword parameterRuby 2.0 and Ruby 2.1

• Caller: make a Hash object and pass it normally• Same as Ruby 2.0 and before

• Callee: decompose a Hash object and assign to local variables correctly• Mostly same code of decomposing code in Ruby

• Need some more error checking

Page 52: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Implementation of keyword parameterRuby 2.0 and Ruby 2.1

def foo(k1: v1, k2: v2)

end

def foo(h={})

k1 = h.fetch(:k1, v1)

k2 = h.fetch(:k2, v2)

#(and error check code)

end

Compiler translate to

Page 53: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Bad NEWSSlow keyword parameters

0

5

10

15

20

foo6(1, 2, 3, 4, 5, 6) foo_kw6(k1: 1, k2: 2, k3: 3, k4: 4,k5: 5, k6: 6)Ex

ecu

tio

n t

ime

(se

c)

Repeat 10M times

Evaluation on Ruby 2.1x30 slower

Page 54: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Why slow, compare with normal parameters?

1. Hash creation

2. Hash accessdef foo(h = {})

k1 = h.fetch(:k1, v1)

k2 = h.fetch(:k2, v2)

end

foo( {k1: 1, k2: 2} )

def foo(k1: v1, k2: v2)

end

foo(k1: 1, k2: 2)

1. Hash creation

2. Hash access

Page 55: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Optimization technique of keyword parameters from Ruby 2.2

•Key technique

→ Pass “a keyword list” instead of a Hash object

Page 56: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Preparation: Make “keyword list” and “default value list” at compile time

• We can see all source code at compile time

• Collect keywords in a list for each method call

• ex: “foo(k1: x, k2: y)” #=> kwlist is [:k1, :k2]

• Collect “Receive keyword list (Rkwlist)” and “Default values list (dvlist)” in each method definition

• ex: “def foo(k1: 1, k2: 2)” #=> Rkwlist is [:k1, :k2],

dvlist is [1, 2]

• ex: “def foo(k1: 1, k2: f2()) #=> dvlist is [1, Qundef]

NOTE: Qundef is internal special valuewhich should not expose Ruby world

Page 57: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Call with keyword parameter [Sender]Pass “kwlist” instead of making a Hash

• Pass values as a “keyword list”

foo(1, 2, kwlist)

foo(k1: 1, k2: 2)

NOTE: This is pseudo code.kwlist is not passed as an argument,but passed as calling information.

Page 58: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Call with keyword parameter [Receiver]Manipulate passed kwlist

• Assign local variables with passed keyword list

def foo(*kvs, kwlist)

Rkwlist.each.with_index{|k, i|

ki = kwlist.index(k)

assign(k, ki ? kvs[ki] : dvlist[i])

}

def foo(k1: 1, k2: 2, k3: 3)

kvs = [1, 2]; kwlist=[:k1, :k2]Rkwlist = [:k1, :k2, :k3]dvlist = [1, 2, 3]Pseudo code

Page 59: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Call with keyword parameter [Receiver]Treat with default values with expressions

def foo(*kvs, kwlist)

unset_bits = 0

Rkwlist.each.with_index{|k, i|

if ki = kwlist.index(k)

v = kvs[ki]

else if (v = dvlist[i]) == Qundef

v = nil

unset_bits[i] = 1

end

assign(k, v)

} # cont to right

# k1 is already initialized

k2 = f2() unless unset_bits[1]

k3 = f3() unless unset_bits[2]

… # start of method body

end

def foo(k1: 1, k2: f2(), k3: f3())

Rkwlist = [:k1, :k2, :k3]dvlist = [1, Qundef, Qundef]Pseudo code

NOTE: Qundef is internal special valuewhich should not expose Ruby world

Using BITMAP to rememberunspecified keywords

Page 60: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Q. Why not assign Qundefdirectly? (instead of using bitmap)

def foo(*kvs, kwlist)

unset_bits = 0

Rkwlist.each.with_index{|k, i|

ki = kwlist.index(k)

v = ki ? kvs[i] : dvlist[i]

assign(k, v)

}

k2 = f2() unless k2 == Qundef

k3 = f3() unless k3 == Qundef

… # start of method body

end

def foo(k1: 1, k2: f2(), k3: f3())

Rkwlist = [:k1, :k2, :k3]dvlist = [1, Qundef, Qundef]Pseudo code

ADVANCED

Page 61: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

A. We can access initializing keyword variables with eval()

def foo(k1: 1,

k2: eval(“k3”), # should be nil

k3: f3())

ADVANCED

Page 62: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Evaluation resultCompare 3 types methods1. def foo6(a, b, c, d, e, f); end

• Normal method dispatch with 6 parameters

2. def foo_kw6(k1: 1, k2: 2, k3: 3, k4: 4, k5: 5, k6: 6); end• Default values are immediate values

3. def foo_complex_kw6(k1: 1+1, k2: 2+1, k3: 3+1, k4: 4+1, k5: 5+1, k6: 6+1); end• Default values are expressions (not

immediate values)

Page 63: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Result: Fast keyword parameters

0

5

10

15

20

foo6(1, 2, 3, 4, 5, 6) foo_kw6(k1: 1, k2: 2, k3: 3, k4: 4, k5:5, k6: 6)

Exec

uti

on

tim

e (s

ec)

Repeat 10M times

Ruby 2.1 Ruby 2.2

x14 faster!!(best case)

But still x2 times slower compare with normal dispatch

Ruby 2.2 optimizes method dispatch with keyword parameters

Page 64: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Result: Ruby 2.1 vs. Ruby 2.2

0

5

10

15

20

Exec

uti

on

tim

e (s

ec)

Ruby 2.1 Ruby 2.2

Removing Hash creation is dramatically effective.

Page 65: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Result: Ruby 2.2

0

0.5

1

1.5

2

foo6(1, 2, 3, 4, 5, 6) foo_kw6 foo_kw6(k1: 1, k2:2, k3: 3, k4: 4, k5: 5,

k6: 6)

foo_complex_kw6 foo_complex_kw6k1: 1, k2: 2, k3: 3,k4: 4, k5: 5, k6: 6

Exec

uti

on

tim

e (s

ec)

Using immediate default values is effective

Using immediate values Using non-immediate values

Page 66: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Challenge:Improve computational complexity• Computational complexity of current impl. is O(mn)

• Now, m and n is enough small (only a few keywords), but…

def foo(*kvs, kwlist)

Rkwlist.each.with_index{|k, i| # m times

ki = kwlist.index(k) → O(m)

Pseudo code

O(n)

n = kwlist.lengthm = Rkwlist.length

Total computationan complexity: O(mn)

Page 67: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

SummaryRuby 2.2 optimized

“keyword parameters”

0

5

10

15

20

foo6(1, 2, 3, 4, 5, 6) foo_kw6(k1: 1, k2: 2, k3: 3, k4: 4,k5: 5, k6: 6)

Exec

uti

on

tim

e (s

ec)

Repeat 10M times

Ruby 2.1 Ruby 2.2

x14 faster!!

But still x2 times slower compare with normal dispatch

Page 68: Evolution of Keyword parametersatdot.net/~ko1/activities/2015_RubyConfPortgual.pdf · Ruby 2.2 Symbol GC Issues history •Ruby 2.2.0 has memory (object) leak problem •Symbols has

Thank you for your attentionArigato!

Koichi Sasada<[email protected]>