Go / Scala
Реализация конструкций языка Go в Scala
Руслан Шевченко
<ruslan@shevchenko.kiev.ua>
https://github.com/rssh/sca...
Что такое в go ?

области видимости (scope)

( defer/ panic / destroy )

параллелизм

channels

select statement

От...
С defer
def copy(inf: File, outf: File): Long = goScope {
val in = new FileInputStream(inf)
defer{ in.close() }
val out = ...
Традиционно:
def copy(inf: File, outf: File): Long =
{
val in = new FileInputStream(inf)
try {
val out = new FileOutputStr...
def copy(inf: File, outf: File): Long = goScope {
val in = new FileInputStream(inf)
defer{ in.close() }
val out = new File...
try
try
try
finally
finally
finally
op/defer
Как это реализовано в scala:

Макросы

Передача параметров по имени

Традиционный try/cath
goScope = .... (macro, в кот...
def copy(inf: File, outf: File): Long = {
val sc0 = new ScopeContext();
sc0.eval {
val in = new FileInputStream(inf)
sc0.p...
Scope: defer / panic / recover

panic => throw new PanicException()

Recover => return
try {
....
} catch {
case ex: Exc...
Channels
Read:
go: channel -> x
Scala:
channel ~> x
x = channel ?
?!
??
Write
go: channel <- x
Scala:
channel <~ x
channel...
Select
Каналы соединяют потоки исполнения
go func() {
for {
select {
case msg1 := <- c1:
fmt.Println(msg1)
case msg2 := <- c2:
fmt.Println(msg2)
}
}
}()
Go: типичны...
go
for(s <- select) s match {
case c1 ~> (msg1: Msg1Type) => println(msg1)
case c2 ~>(msg2:Msg2Type) => println(msg2)
}
Sc...
Без сахара (упрощенно) [1]:
go {
val s = new SelectContext();
s.addReader(c1) {
(msg1:Msg1Type) => println(msg1)
}
s.addRe...
Без сахара (упрощенно) [2]:
val scope = new ScopeContext();
val s = new SelectContext();
Future {
s.addReader(c1) {
(msg1:...
Select вне цикла:
for(s <- select.once) s match {
case c1 ~> (msg1: Msg1Type) => println(msg1)
case c2 ~>(msg2:Msg2Type) =...
Текущая внутренняя реализация:

Активная очередь

Channel = [Blocked Query + Execution Context ]
• Select: координационн...
val consumer = go {
for(s <- select) {
s match {
case `channel` ~> (i:Int) =>
sum = sum + i
if (i==1000) s.shutdown()
}
}
...
Akka
(как в Erlang)
Channels (как в go)

Реактивные

Неблокирующие
операции

Запрос/Ответ
парадигма

При перегрузке -
...
x1, x2, x3, ............
x1*y1, x2*y2, x3*y3, ............
y1, y2, y3, ............
go {
while(;) {
val x = channelX ?
val...
bindWrite
bindRead
? [блокирующие операции в акторе]
Что дальше

Новый “базис”
[select in loop in go] - слишком фундаментально,
что бы быть комбинацией 3-х конструкций.

Аль...
Подключаемые реализации.

Существует много стратегий.
(текущая реализация не лучшая)
– Schedule/callback вместо waits
– С...
Переписывание в реактивную форму
- Процесс, аналогичный СPS - но легче
go {
...
val x = channelX ?
val y = channelY ?
channelZ ! x*y
...
}
go { .....
channelX.read map { x =>
channelY.read map ...
someCollection foldLeft {
(s,x) => s + (x* channel ?)
}
Такая же проблема, как и с CPS:
- foldLeft не наш.
- foreach не на...
Поддержка сопрограм в JVM
- Изменение JVM
- Переписывание байт-кода
- Ничего не делать – thread pool большой
(нагрузить wa...
The Da Vinci machine
http://openjdk.java.net/projects/mlvm/index.html
AVIAN VM
http://oss.readytalk.com/avian/
Когда нибудь – все будет хорошо.
а пока – вот вам котик
Continuations: Bytecode rewriting.
Frames:
a) Вместо возрата – копируем фрейм.
foldLeft
? channel
+
*
Continuations: Bytecode rewriting.
Frames:
foldLeft
+
*
Continuations: Bytecode rewriting.
Frames:
Suspended
Применение CPS к байт-коду
foldLeft
+
*
Channel ?
Помощь сообщества.
https://github.com/rssh/scala-gopher

Примеры использования.

Инструментирование и профилирование

Л...
implementation of 'go'-like language constructions in scala (russian)
implementation of 'go'-like language constructions in scala (russian)
Upcoming SlideShare
Loading in...5
×

implementation of 'go'-like language constructions in scala (russian)

387

Published on

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

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
387
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
6
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "implementation of 'go'-like language constructions in scala (russian)"

  1. 1. Go / Scala Реализация конструкций языка Go в Scala Руслан Шевченко <ruslan@shevchenko.kiev.ua> https://github.com/rssh/scala-gopher
  2. 2. Что такое в go ?  области видимости (scope)  ( defer/ panic / destroy )  параллелизм  channels  select statement  Отличие от 'родного' подхода в scala  Как реализовать 'go' вариант Что дальше ...
  3. 3. С defer 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(); } } По старому:
  4. 4. Традиционно: 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(); } }
  5. 5. 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
  6. 6. try try try finally finally finally op/defer
  7. 7. Как это реализовано в scala:  Макросы  Передача параметров по имени  Традиционный try/cath goScope = .... (macro, в котором переписывается аргумент) defer => @compileTimeOnly
  8. 8. 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]() } Без сахара:
  9. 9. Scope: defer / panic / recover  panic => throw new PanicException()  Recover => return try { .... } catch { case ex: Exception => return x } defer{ ......... recover(x) }
  10. 10. Channels Read: go: channel -> x Scala: channel ~> x x = channel ? ?! ?? Write go: channel <- x Scala: channel <~ x channel ! x !! (немедленно) !? (через таймоут)
  11. 11. Select Каналы соединяют потоки исполнения
  12. 12. go func() { for { select { case msg1 := <- c1: fmt.Println(msg1) case msg2 := <- c2: fmt.Println(msg2) } } }() Go: типичный паттерн: select внутри for внутри goroutine
  13. 13. go for(s <- select) s match { case c1 ~> (msg1: Msg1Type) => println(msg1) case c2 ~>(msg2:Msg2Type) => println(msg2) } Scala аналог: - реализован как макрос foreach - ~> в образце: надо указывать тип - активная очередь Открытый вопрос: хороший “родной” не-макро синтаксис
  14. 14. Без сахара (упрощенно) [1]: go { val s = new SelectContext(); s.addReader(c1) { (msg1:Msg1Type) => println(msg1) } s.addReader(c2) { (msg2:Msg2Type) => println(msg2) } s.run() }
  15. 15. Без сахара (упрощенно) [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() } (Дальнейшая работа) S
  16. 16. 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
  17. 17. Текущая внутренняя реализация:  Активная очередь  Channel = [Blocked Query + Execution Context ] • Select: координационные примитивы + wait [oops...] – Count down latch – Memory barrier  Расширения по сравнению с моделью Go  Асинхронные операции  Остановка контекста (context shutdown).
  18. 18. val consumer = go { for(s <- select) { s match { case `channel` ~> (i:Int) => sum = sum + i if (i==1000) s.shutdown() } } sum } Future[Int]
  19. 19. Akka (как в Erlang) Channels (как в go)  Реактивные  Неблокирующие операции  Запрос/Ответ парадигма  При перегрузке - mailbox overflow при send  Что-то обработать.  Потоково ориентированные  Wait это нормально (переключение потоков в это время)  Однонаправленная труба  При перегрузке ожидание при send  Что-то посчитать
  20. 20. x1, x2, x3, ............ x1*y1, x2*y2, x3*y3, ............ y1, y2, y3, ............ go { while(;) { val x = channelX ? val y = channelY ? channelZ ! x*y } } Пример: Легко с gopher, сложно с Akka
  21. 21. bindWrite bindRead ? [блокирующие операции в акторе]
  22. 22. Что дальше  Новый “базис” [select in loop in go] - слишком фундаментально, что бы быть комбинацией 3-х конструкций.  Альтернативный синтаксис с явной реактивностью  Заставить работь вывод типов  Подключаемые (pluggable) реализации  Оптимизировать крайние случаи
  23. 23. Подключаемые реализации.  Существует много стратегий. (текущая реализация не лучшая) – Schedule/callback вместо waits – Собственный dispatcher – ..... Тесты производительности, Цикл “прототипирование / тест” Проблемы - отсутсвие механизма импорта модулей @exported import - JVM Помощь сообщества (?)
  24. 24. Переписывание в реактивную форму - Процесс, аналогичный СPS - но легче
  25. 25. 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 } } } } }
  26. 26. someCollection foldLeft { (s,x) => s + (x* channel ?) } Такая же проблема, как и с CPS: - foldLeft не наш. - foreach не наш и непонятно, что там for(x <- something) channel <~~ x отсуствие поддержки сопрограмм в JVM
  27. 27. Поддержка сопрограм в JVM - Изменение JVM - Переписывание байт-кода - Ничего не делать – thread pool большой (нагрузить wait выполнением заведомо неблокирующих задач)
  28. 28. The Da Vinci machine http://openjdk.java.net/projects/mlvm/index.html AVIAN VM http://oss.readytalk.com/avian/
  29. 29. Когда нибудь – все будет хорошо. а пока – вот вам котик
  30. 30. Continuations: Bytecode rewriting. Frames: a) Вместо возрата – копируем фрейм. foldLeft ? channel + *
  31. 31. Continuations: Bytecode rewriting. Frames: foldLeft + *
  32. 32. Continuations: Bytecode rewriting. Frames: Suspended Применение CPS к байт-коду foldLeft + * Channel ?
  33. 33. Помощь сообщества. https://github.com/rssh/scala-gopher  Примеры использования.  Инструментирование и профилирование  Лучшие реализации . Давайте подумаем вместе. Спасибо за внимание. Ruslan Shevchenko <Ruslan@Shevchenko.Kiev.UA>
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×