Какая из сопрограмм (goroutines и kotlin сопрограммы) быстрее?

Kotlin corutines - это сахар для конечного автомата и некоторый бегун (например, по умолчанию ForkJoinPool). https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md#implementation-details

Другими словами, пока нет исполняемых команд runtime в java/kotlin (но это может измениться с помощью http://cr.openjdk.java.net/~rpressler/loom/Loom-Proposal.html). Kotlin coroutine - это просто последовательность задач, которые выполняются один за другим. Каждая задача может быть выполнена в любом потоке из пула потоков.

Go runtime поддерживает "сопрограммы". Но goroutines - не настоящие сопрограммы. Goroutines не позволяет задавать точки урожая в программе. Кроме того, Go не позволяет установить собственный пул потоков. Вы можете установить только размер потоков в пуле по умолчанию.

Первое различие между kotlin coroutines и goroutines - Go runtime управляет тем, что coroutine работает в данный момент. Когда gotoutine блокируются при некоторой операции ввода-вывода (или примитивах синхронизации), Go выбирает следующий Job для его выполнения. В JVM нет интеллектуального переключения работы в таких условиях.

Из-за этого Go может дешево изменить текущую работу. Go должен только изменить несколько реестров https://groups.google.com/forum/#!msg/golang-nuts/j51G7ieoKh4/wxNaKkFEfvcJ. Но некоторые люди говорят, что JVM может использовать стек потоков вместо использования регистров. Таким образом, нет никакой экономии и загрузки регистров.

Второе различие между kotlin coroutines и goroutines - это тип сопрограмм. Kotlin coroutines - это стекированные сопрограммы. Горотины - это многоуровневые сопрограммы. Все состояния сопрограмм Kotlin хранятся в контексте Котлина, который хранится в куче. Состояние Goroutines хранится в регистрах и стеках потоков.

Я хочу знать, какие сопрограммы (goroutines и kotlin coroutines) быстрее выполняются в задачах, связанных с IO? Задачи, связанные с процессором? Как насчет потребления памяти?

Ответ 1

Коутины в Котлине реализованы иначе, чем goroutines в Go, поэтому один из них "быстрее" зависит от проблемы, которую вы решаете, и типа кода, который вы пишете.

В общем, очень сложно заранее сказать, какой из них будет лучше работать, если у вас есть проблема. Вы должны запустить тесты для своих конкретных рабочих нагрузок, чтобы понять это. Однако здесь приводится общее резюме ключевых различий, которые должны дать вам некоторые рекомендации.

  • Kotlin coroutines требует меньше памяти на простой экземпляр, чем Go goroutines. Простая сопрограмма в Котлин занимает всего несколько десятков байтов памяти кучи, а Go goroutine начинается с 4KiB пространства стека. Это означает, что если вы планируете иметь буквально миллионы сопрограмм, то сопрограммы в Котлине могут дать вам преимущество против Go. Это также делает Kotlin coroutines лучше подходящим для очень коротких и небольших задач, таких как генераторы и ленивые последовательности.

  • Kotlin coroutines может перейти на любую глубину стека, однако каждый вызов функции приостановки выделяет объект в кучу для своего стека. В настоящее время стек вызовов в котинах Kotlin реализуется как связанный список объектов кучи. Напротив, goroutines в Go используют пространство линейного стека. Это делает подвеску на глубоких стеках более эффективной в Go. Итак, если код, который вы пишете, очень сильно подвешивает стек, вы можете обнаружить, что goroutines более эффективны для вас.

  • Эффективный асинхронный IO является очень многомерной проблемой проектирования. Подход, который эффективен для одного типа приложений, не может дать лучшую производительность другому. Все операции ввода-вывода в сопрограммах Kotlin реализованы библиотеками, написанными в Kotlin или Java. Существует огромное количество библиотек IO, доступных для кода Kotlin. В Go асинхронный IO реализуется Go runtime с использованием примитивов, которые недоступны для общего кода Go. Если подход Go к внедрению операций ввода-вывода хорошо подходит для вашего приложения, вы можете обнаружить, что его тесная интеграция с временем выполнения Go дает вам преимущество. С другой стороны, в Котлине вы можете найти библиотеку или написать ее самостоятельно, которая реализует асинхронный ввод-вывод таким образом, который лучше всего подходит для вашего приложения.

  • Go runtime полностью контролирует выполнение расписаний goroutines в потоках физической ОС. Преимущество такого подхода заключается в том, что вам не нужно думать обо всем этом. С Kotlin coroutines у вас есть мелкомасштабный контроль над средой исполнения ваших сопрограмм. Это подвержено ошибкам (например, вы можете просто создавать слишком много разных пулов потоков и тратить свое процессорное время на переключение контекста между ними). Тем не менее, это дает вам возможность точно настроить распределение потоков и контекстные параметры для вашего приложения. Например, в Kotlin легко выполнить все ваше приложение или подмножество его кода в одном потоке ОС (или пуле потоков), чтобы полностью избежать переключения контекстов между потоками ОС, просто написав для этого соответствующий код.