SlideShare a Scribd company logo
Go / Scala
Реализация конструкций языка Go в Scala
Руслан Шевченко
<ruslan@shevchenko.kiev.ua>
https://github.com/rssh/scala-gopher
Что такое в go ?

области видимости (scope)

( defer/ panic / destroy )

параллелизм

channels

select statement

Отличие от 'родного' подхода в scala

Как реализовать 'go' вариант
Что дальше ...
С 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();
}
}
По старому:
Традиционно:
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();
}
}
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
try
try
try
finally
finally
finally
op/defer
Как это реализовано в scala:

Макросы

Передача параметров по имени

Традиционный try/cath
goScope = .... (macro, в котором
переписывается аргумент)
defer => @compileTimeOnly
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]()
}
Без сахара:
Scope: defer / panic / recover

panic => throw new PanicException()

Recover => return
try {
....
} catch {
case ex: Exception =>
return x
}
defer{
.........
recover(x)
}
implementation of 'go'-like language constructions in scala (russian)
Channels
Read:
go: channel -> x
Scala:
channel ~> x
x = channel ?
?!
??
Write
go: channel <- x
Scala:
channel <~ x
channel ! x
!! (немедленно)
!? (через таймоут)
implementation of 'go'-like language constructions in scala (russian)
Select
Каналы соединяют потоки исполнения
go func() {
for {
select {
case msg1 := <- c1:
fmt.Println(msg1)
case msg2 := <- c2:
fmt.Println(msg2)
}
}
}()
Go: типичный паттерн:
select внутри for внутри goroutine
go
for(s <- select) s match {
case c1 ~> (msg1: Msg1Type) => println(msg1)
case c2 ~>(msg2:Msg2Type) => println(msg2)
}
Scala аналог:
- реализован как макрос foreach
- ~> в образце: надо указывать тип
- активная очередь
Открытый вопрос: хороший “родной” не-макро синтаксис
Без сахара (упрощенно) [1]:
go {
val s = new SelectContext();
s.addReader(c1) {
(msg1:Msg1Type) => println(msg1)
}
s.addReader(c2) {
(msg2:Msg2Type) => println(msg2)
}
s.run()
}
Без сахара (упрощенно) [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
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
Текущая внутренняя реализация:

Активная очередь

Channel = [Blocked Query + Execution Context ]
• Select: координационные примитивы + wait [oops...]
– Count down latch
– Memory barrier

Расширения по сравнению с моделью Go

Асинхронные операции

Остановка контекста (context shutdown).
val consumer = go {
for(s <- select) {
s match {
case `channel` ~> (i:Int) =>
sum = sum + i
if (i==1000) s.shutdown()
}
}
sum
}
Future[Int]
Akka
(как в Erlang)
Channels (как в go)

Реактивные

Неблокирующие
операции

Запрос/Ответ
парадигма

При перегрузке -
mailbox overflow при send

Что-то обработать.

Потоково ориентированные

Wait это нормально
(переключение потоков в это время)

Однонаправленная труба

При перегрузке
ожидание при send

Что-то посчитать
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
bindWrite
bindRead
? [блокирующие операции в акторе]
Что дальше

Новый “базис”
[select in loop in go] - слишком фундаментально,
что бы быть комбинацией 3-х конструкций.

Альтернативный синтаксис
с явной реактивностью

Заставить работь вывод типов

Подключаемые (pluggable) реализации

Оптимизировать крайние случаи
Подключаемые реализации.

Существует много стратегий.
(текущая реализация не лучшая)
– Schedule/callback вместо waits
– Собственный dispatcher
– .....
Тесты производительности,
Цикл “прототипирование / тест”
Проблемы
- отсутсвие механизма импорта модулей
@exported import
- JVM
Помощь сообщества (?)
Переписывание в реактивную форму
- Процесс, аналогичный СPS - но легче
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
} } }
}
}
someCollection foldLeft {
(s,x) => s + (x* channel ?)
}
Такая же проблема, как и с CPS:
- foldLeft не наш.
- foreach не наш и непонятно, что там
for(x <- something) channel <~~ x
отсуствие поддержки сопрограмм в JVM
Поддержка сопрограм в JVM
- Изменение JVM
- Переписывание байт-кода
- Ничего не делать – thread pool большой
(нагрузить wait выполнением
заведомо неблокирующих задач)
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

Примеры использования.

Инструментирование и профилирование

Лучшие реализации .
Давайте подумаем вместе. Спасибо за внимание.
Ruslan Shevchenko
<Ruslan@Shevchenko.Kiev.UA>

More Related Content

PDF
Для чего мы делали свой акторный фреймворк и что из этого вышло?
PDF
Семь тысяч Rps, один go
PPTX
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
PDF
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
PDF
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
PDF
RDSDataSource: Чистые тесты на Swift
PPTX
Профайлинг.
PDF
Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Семь тысяч Rps, один go
Сергей Шамбир, Адаптация Promise/A+ для взаимодействия между C++ и Javascript
Полухин Антон, Как делать не надо: C++ велосипедостроение для профессионалов
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
RDSDataSource: Чистые тесты на Swift
Профайлинг.
Библиотеки для передачи данных (Lecture 13 – multithreading, network (libs))

What's hot (20)

PDF
Haskell
PDF
Reform: путь к лучшему ORM
PPTX
Евгений Зуев, С++ в России: Стандарт языка и его реализация
PDF
Parallel STL
PDF
JavaDay'14
PPTX
Оптимизация трассирования с использованием Expression templates
PDF
Android - 11 - Multithreading
PPTX
Async clinic by by Sergey Teplyakov
PPTX
Александр Фокин, Рефлексия в C++
PDF
Использование юнит-тестов для повышения качества разработки
PPTX
Deep Dive C# by Sergey Teplyakov
PDF
Борис Сазонов, RAII потоки и CancellationToken в C++
PDF
RxJava+RxAndroid (Lecture 20 – rx java)
PPTX
Григорий Демченко, Асинхронность и неблокирующая синхронизация
PDF
Очереди и блокировки
PDF
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
PDF
JPoint 2015 - Javassist на службе Java-разработчика
PDF
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
PPTX
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
PDF
Практика Lock-free. RealTime-сервер
Haskell
Reform: путь к лучшему ORM
Евгений Зуев, С++ в России: Стандарт языка и его реализация
Parallel STL
JavaDay'14
Оптимизация трассирования с использованием Expression templates
Android - 11 - Multithreading
Async clinic by by Sergey Teplyakov
Александр Фокин, Рефлексия в C++
Использование юнит-тестов для повышения качества разработки
Deep Dive C# by Sergey Teplyakov
Борис Сазонов, RAII потоки и CancellationToken в C++
RxJava+RxAndroid (Lecture 20 – rx java)
Григорий Демченко, Асинхронность и неблокирующая синхронизация
Очереди и блокировки
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++
JPoint 2015 - Javassist на службе Java-разработчика
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Евгений Рыжков, Андрей Карпов Как потратить 10 лет на разработку анализатора ...
Практика Lock-free. RealTime-сервер
Ad

Viewers also liked (9)

PDF
Few simple-type-tricks in scala
PDF
Why scala is not my ideal language and what I can do with this
PDF
Scala jargon cheatsheet
PDF
Лев Валкин — Кое-что про Erlang
PDF
Csp scala wixmeetup2016
PDF
Java & low latency applications
PDF
Erlang мгновенное просветление
Few simple-type-tricks in scala
Why scala is not my ideal language and what I can do with this
Scala jargon cheatsheet
Лев Валкин — Кое-что про Erlang
Csp scala wixmeetup2016
Java & low latency applications
Erlang мгновенное просветление
Ad

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

PPTX
Зачем нужна Scala?
PDF
Язык программирования Go для Perl-программистов
PDF
Clojure #2 (2014)
PDF
Haskell Lite - presentation for DevDay about Haskell language
PDF
JPoint 2016 - Etudes of DIY Java profiler
PDF
Groovy presentation.
PDF
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
PPTX
Clojure: Lisp for the modern world (русская версия)
PDF
Михаил Давыдов — JavaScript: Базовые знания
PPT
Характерные черты функциональных языков программирования
PDF
Лекция о языке программирования Haskell
PDF
Java 8 puzzlers
PPT
Mike ponomarenko java17-fork-v1.2
PDF
Scala for android
PDF
Scala on android
PPTX
PHP7 - что ожидать?
PPTX
Оптимизация трассирования с использованием Expression templates
PPTX
PowerShell
PDF
Введение в Clojure (Margincon 2010)
PDF
Java 9: what is there beyond modularization
Зачем нужна Scala?
Язык программирования Go для Perl-программистов
Clojure #2 (2014)
Haskell Lite - presentation for DevDay about Haskell language
JPoint 2016 - Etudes of DIY Java profiler
Groovy presentation.
Стажировка 2016-07-14 02 Евгений Тарасенко. JavaScript
Clojure: Lisp for the modern world (русская версия)
Михаил Давыдов — JavaScript: Базовые знания
Характерные черты функциональных языков программирования
Лекция о языке программирования Haskell
Java 8 puzzlers
Mike ponomarenko java17-fork-v1.2
Scala for android
Scala on android
PHP7 - что ожидать?
Оптимизация трассирования с использованием Expression templates
PowerShell
Введение в Clojure (Margincon 2010)
Java 9: what is there beyond modularization

More from Ruslan Shevchenko (20)

PDF
Embedding Generic Monadic Transformer into Scala. [Tfp2022]
PDF
Svitla talks 2021_03_25
PDF
Akka / Lts behavior
PDF
Papers We Love / Kyiv : PAXOS (and little about other consensuses )
PDF
Scala / Technology evolution
PDF
{co/contr} variance from LSP
PDF
N flavors of streaming
PDF
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
PDF
SE 20016 - programming languages landscape.
PDF
R ext world/ useR! Kiev
PDF
Jslab rssh: JS as language platform
PDF
Behind OOD: domain modelling in post-OO world.
PDF
scala-gopher: async implementation of CSP for scala
PDF
Programming Languages: some news for the last N years
PDF
JDays Lviv 2014: Java8 vs Scala: Difference points & innovation stream
PDF
Ruslan.shevchenko: most functional-day-kiev 2014
PDF
Web architecture - overview of techniques.
PDF
R scala 17_05_2014
ODP
Javascript in modern scala backend. [russian]
PDF
Osdn2013 rssh
Embedding Generic Monadic Transformer into Scala. [Tfp2022]
Svitla talks 2021_03_25
Akka / Lts behavior
Papers We Love / Kyiv : PAXOS (and little about other consensuses )
Scala / Technology evolution
{co/contr} variance from LSP
N flavors of streaming
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
SE 20016 - programming languages landscape.
R ext world/ useR! Kiev
Jslab rssh: JS as language platform
Behind OOD: domain modelling in post-OO world.
scala-gopher: async implementation of CSP for scala
Programming Languages: some news for the last N years
JDays Lviv 2014: Java8 vs Scala: Difference points & innovation stream
Ruslan.shevchenko: most functional-day-kiev 2014
Web architecture - overview of techniques.
R scala 17_05_2014
Javascript in modern scala backend. [russian]
Osdn2013 rssh

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

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