35
Go / Scala Implementation of go language constructions in scala Ruslan Shevchenko <[email protected] > https://github.com/rssh/scala-gopher

Implementation of 'go-like' language constructions in scala [english version]

Embed Size (px)

DESCRIPTION

Presentation about implementation of go-like language constructions in scala: https://github.com/rssh/scala-gopher

Citation preview

Page 1: Implementation of 'go-like' language constructions in scala [english version]

Go / Scala

Implementation of go language constructions in scala

Ruslan Shevchenko<[email protected]>

https://github.com/rssh/scala-gopher

Page 2: Implementation of 'go-like' language constructions in scala [english version]

Whats in go ?

scope ( defer/ panic / destroy )

parallelism channels select statement

Differences from 'native' scala approach How to implement go variant

Future directions...

Page 3: Implementation of 'go-like' language constructions in scala [english version]

Scope

def copy(inf: File, outf: File): Long = goScope { val in = new FileInputStream(inf) defer{ in.close() } val out = new FileOutputStream(outf); defer{ out.close() } out.getChannel() transferFrom(in.getChannel(), 0, Long.MaxValue) }

def copy(inf: File, outf: File): Long = { val in = new FileInputStream(inf) try { val out = new FileOutputStream(outf) try { out.getChannel() transferFrom(in.getChannel(), 0, Long.MaxValue) } finally { out.close(); } } finally { in.close(); }}

Old way:

Page 4: Implementation of 'go-like' language constructions in scala [english version]

Traditional way:

def copy(inf: File, outf: File): Long = { val in = new FileInputStream(inf) try { val out = new FileOutputStream(out) try { out.getChannel() transferFrom(in.getChannel(), 0,Long.MaxValue) } finally { out.close(); } } finally { in.close(); }}

Page 5: Implementation of 'go-like' language constructions in scala [english version]

def copy(inf: File, outf: File): Long = goScope { val in = new FileInputStream(inf) defer{ in.close() } val out = new FileOutputStream(outf); defer{ out.close() } out.getChannel() transferFrom(in.getChannel(), 0, Long.MaxValue) }

Go way

Page 6: Implementation of 'go-like' language constructions in scala [english version]

try

try

try

finally

finally

finally

op/defer

Page 7: Implementation of 'go-like' language constructions in scala [english version]

How this done is scala:

Macroses Call-by-name-params Traditional try/cath

goScope = .... (macro wich rewrite arg)

defer => @compileTimeOnly

Page 8: Implementation of 'go-like' language constructions in scala [english version]

def copy(inf: File, outf: File): Long = { val sc0 = new ScopeContext(); sc0.eval { val in = new FileInputStream(inf) sc0.pushDefer{ in.close() } val out = new FileOutputStream(outf); sc0.pushDefer{ out.close() } out.getChannel() transferFrom(in.getChannel(), 0, Long.MaxValue) } sc0.unwindDefers[Long]() }

Unsugared:

Page 9: Implementation of 'go-like' language constructions in scala [english version]

Scope: defer / panic / recover

panic => throw new PanicException() Recover => return

try { ....} catch { case ex: Exception => return x}

defer{ ......... recover(x)}

Page 10: Implementation of 'go-like' language constructions in scala [english version]
Page 11: Implementation of 'go-like' language constructions in scala [english version]

Channels

Read:

go: channel -> x

Scala: channel ~> x x = channel ? ?! ??

Writego: channel <- x

Scala: channel <~ x channel ! x !! (immediatly) !? (with timeout)

Page 12: Implementation of 'go-like' language constructions in scala [english version]
Page 13: Implementation of 'go-like' language constructions in scala [english version]

Select

Channels connect execution flows

Page 14: Implementation of 'go-like' language constructions in scala [english version]

go func() { for { select { case msg1 := <- c1: fmt.Println(msg1) case msg2 := <- c2: fmt.Println(msg2) } } }()

Go: typical pattern: select inside for inside goroutine

Page 15: Implementation of 'go-like' language constructions in scala [english version]

go for(s <- select) s match { case c1 ~> (msg1: Msg1Type) => println(msg1) case c2 ~>(msg2:Msg2Type) => println(msg2) }

Scala Analog:

- implemented as foreach macros- ~> pattern: require typing- active queue

Open question: native non-macro syntax

Page 16: Implementation of 'go-like' language constructions in scala [english version]

Unsugared (simplicified) [1]:

go { val s = new SelectContext(); s.addReader(c1) { (msg1:Msg1Type) => println(msg1) } s.addReader(c2) { (msg2:Msg2Type) => println(msg2) } s.run()}

Page 17: Implementation of 'go-like' language constructions in scala [english version]

Unsugared (simplicified) [2]:

val scope = new ScopeContext(); val s = new SelectContext();Future { s.addReader(c1) { (msg1:Msg1Type) => println(msg1) } s.addReader(c2) { (msg2:Msg2Type) => println(msg2) }} map { s.runUnblocked() } map { scope.finish() }

(Future work)

S

Page 18: Implementation of 'go-like' language constructions in scala [english version]

Just select:

for(s <- select.once) s match { case c1 ~> (msg1: Msg1Type) => println(msg1) case c2 ~>(msg2:Msg2Type) => println(msg2) }

select { case msg1 := <- c1: fmt.Println(msg1) case msg2 := <- c2: fmt.Println(msg2)}

GO

SCALA

Page 19: Implementation of 'go-like' language constructions in scala [english version]

Internal implementation:

Active channel Channel = [Blocked Query + Execution Context ]

Coordination primitives + wait for select Count down latch Memory barrier

Extensions over Go model async operations context shutdown.

Page 20: Implementation of 'go-like' language constructions in scala [english version]

val consumer = go { for(s <- select) { s match { case `channel` ~> (i:Int) => sum = sum + i if (i==1000) s.shutdown() } } sum }

Future[Int]

Page 21: Implementation of 'go-like' language constructions in scala [english version]

Akka (Erlang-like actors)

Channels (go-like)

Reactive No blocking operations

Request/Reply paradigm.

Mailbox overflow on overload

Handle something.

Flow oriented Wait is normal (switch during wait) One-direction pipe paradigm

wait on send On overload

Compute something

Page 22: Implementation of 'go-like' language constructions in scala [english version]

x1, x2, x3, ............

x1*y1, x2*y2, x3*y3, ............

y1, y2, y3, ............

go { while(;) { val x = channelX ? val y = channelY ? channelZ ! x*y }}

Example: Easy with channels, hard with Akka

Page 23: Implementation of 'go-like' language constructions in scala [english version]

bindWritebindRead

? [blocking operation]

Page 24: Implementation of 'go-like' language constructions in scala [english version]

Future directions

Redefining of base primitivies [select in loop in go] is too fundamental, to be combination of 3 constructions.

Native non-macro syntax Make scala type inference works

Pluggable implementations Optimize corner cases

Page 25: Implementation of 'go-like' language constructions in scala [english version]

Pluggable implementations.

Exists many strategies. (current implemented is not best)

Schedule/callback instead waits Play with own dispatcher .....

Performance tests, Implement/Prototype/Test loop,

Problems: Lack of import-based configuration in scala @exported import

Community help needed.

Page 26: Implementation of 'go-like' language constructions in scala [english version]

Rewriting blocking API into reactive

- like CPS (continuations passing style)

Page 27: Implementation of 'go-like' language constructions in scala [english version]

go { ... val x = channelX ? val y = channelY ? channelZ ! x*y ...} go { .....

channelX.read map { x => channelY.read map { y => channelZ.write map { ch => ch <~! x*y } } } }}

Page 28: Implementation of 'go-like' language constructions in scala [english version]

someCollection foldLeft { (s,x) => s + (x* channel ?) }

Problem – same as with CPS: - foldLeft – implemented not here.

- foreach

for(x <- something) channel <~~ x

Continuations not supported directly by JVM

Page 29: Implementation of 'go-like' language constructions in scala [english version]

Continuations in JVM

- Patched JVM - Byte-code rewriting. - Do nothing – thread pools now big (utilize wait by running Flow of non-blocking tasks here)

Page 30: Implementation of 'go-like' language constructions in scala [english version]

The Da Vinci machine

http://openjdk.java.net/projects/mlvm/index.html

AVIAN VM

http://oss.readytalk.com/avian/

Page 31: Implementation of 'go-like' language constructions in scala [english version]

Someday everything will be fine. For now - here is a cat

Page 32: Implementation of 'go-like' language constructions in scala [english version]

Continuations: Bytecode rewriting.

Frames:

Let's save frame during function end, instead deleting one.

foldLeft

? channel

+

*

Page 33: Implementation of 'go-like' language constructions in scala [english version]

Continuations: Bytecode rewriting.

Frames:

foldLeft

+

*

Page 34: Implementation of 'go-like' language constructions in scala [english version]

Continuations: Bytecode rewriting.

Frames:

Suspended

CPS transformation on bytecode level

foldLeft

+

*

Channel ?

Page 35: Implementation of 'go-like' language constructions in scala [english version]

Community help needed.

https://github.com/rssh/scala-gopher

Build examples of typical usage. Instrument ones for performance tests Provide better implementations.

Let's think together. Thanks for attention.

Ruslan Shevchenko <[email protected]>