Здравствуйте, ·, Вы писали:
·>Самый вменяемый код — это на Java
Project Loom это конечно технически очень круто, но я не уверен, что .net надо подобное срочно пилить. Явная(async/await), а не скрытая, монада имеет свои преимущества.
Здравствуйте, novitk, Вы писали:
T>>Делается тривиальный хелпер на три строчки и код будет выглядеть точно так же N>И в результате имеем ровно тоже, что и в .net , но там в отличие от GoLang не забыли про ошибки и как и положено сделали каналы опциональными.
Здравствуйте, mrTwister, Вы писали:
T>Здравствуйте, novitk, Вы писали:
T>>>Делается тривиальный хелпер на три строчки и код будет выглядеть точно так же N>>И в результате имеем ровно тоже, что и в .net , но там в отличие от GoLang не забыли про ошибки и как и положено сделали каналы опциональными.
T>Нет, в .net совсем не тоже, коллега "." тут объяснил разницу: https://rsdn.org/forum/flame.comp/9033106.1
Там о том, что Serginio1 влез не по делу с Task.WhenAll.
T>при этом func1 и func2 — это самые обычные функции, не помеченные никакими async'ами и прочим мусором
Будь они обычные, как в Project Loom, тебе бы RunTask, aka Task.Run, не понадобился. Там семантика результата функций поддерживается в обеих контекстах, а в GoLang только в синхронном.
Здравствуйте, Serginio1, Вы писали:
S>Ну и чем это лучше S>Task.WhenAll
а) WhenAll тут не нужен.
б) Суть в другом. В jvm nет никаких async функций. Любая функция может быть запущена, как синхронно, так и ассинхронно. Решение принимает тот, кто ее вызывает. Сейчас прибежит mrTwister и скажет, что в GoLang тоже. И отчасти он будет прав, но лишь отчасти. Из за криворукости "простоты" там не поддерживается вся семантика в обеих контестах. В частности, если функция вызвана через go, то ее результат получить невозможно. Единственный способ получения результата из ассинхронного вызова это использовать всякие неявные методы (обычно каналы, ну или shared memory), но это требует переписки функций, то есть фактически не сильно отличается от .net.
Здравствуйте, mrTwister, Вы писали:
T>То есть функция начала работать на одном потоке ОС, а закончила на другом потоке. Как это возможно, если бы она не была асинхронной? T>Параллельно я запустил еще десяток горутин без функции Foo, чтобы переезд на тругой тред чаще воспроизводился. Оно воспроизводится и без этого, но не каждый раз, надо просто чаще позапускать (иногда раз 10): https://go.dev/play/p/087bV3w7fMT
Ну вот теперь — верю. Но тут отсутствует возможность получить Promise/Future/Task. Т.е. заготовку под ответ, которую можно куда-то добавить, что-то с ней сделать. Это не удобно.
Здравствуйте, Serginio1, Вы писали:
S>Ну и чем это лучше S>Task.WhenAll
а) WhenAll тут не нужен.
б) Суть в другом. В jvm nет никаких async функций. Любая функция может быть запущена, как синхронно, так и ассинхронно(виртуальные потоки, ака "зеленые"). Решение принимает тот, кто ее вызывает, a не тот кто пишет . При этом, если она запущена на "зеленых", то блокировать OS поток она не будет, даже если там бесконечный цикл и без всяких дотнетовских Task.Yield(). Сейчас прибежит mrTwister и скажет, что в GoLang то же. И отчасти он будет прав, но лишь отчасти. Из за криворукости "простоты" там не поддерживается вся семантика в обеих контестах. В частности, если функция вызвана через go, то ее результат получить невозможно. Единственный способ получения результата из ассинхронного вызова это использовать всякие неявные методы (обычно каналы, ну можно и shared memory), но это требует переписки функций, то есть фактически не сильно отличается от .net.
T>Дальше не читал. Горутина в go — это просто структура данных. Как, например, Task в .net.
Ага.
Собственно, Erlang тем и отличается, что у них process не просто структура данных, а еще и всякие поля для scheduling'а, и структура эта определена в виртуальной машине, а не просто как часть user-space library.
S>>Ну и чем это лучше S>>Task.WhenAll
N>а) WhenAll тут не нужен.
Нужен. Он хочет параллельно выполнять 2 задачи. Хотя в .Net есть еще и Parallel. N>б) Суть в другом. В jvm nет никаких async функций. Любая функция может быть запущена, как синхронно, так и ассинхронно. Решение принимает тот, кто ее вызывает. Сейчас прибежит mrTwister и скажет, что в GoLang тоже. И отчасти он будет прав, но лишь отчасти. Из за криворукости "простоты" там не поддерживается вся семантика в обеих контестах. В частности, если функция вызвана через go, то ее результат получить невозможно. Единственный способ получения результата из ассинхронного вызова это использовать всякие неявные методы (обычно каналы, ну или shared memory), но это требует переписки функций, то есть фактически не сильно отличается от .net.
Они тоже мучаются с корутинами. В .Net же Linq компилятор генерирует класс с автоматом.
Компилятор C# действительно генерирует скрытый класс-автомат (State Machine) для LINQ-выражений (особенно для тех, что используют yield return и foreach), который хранит состояние и разбивает выполнение метода на секции, что позволяет ему «замораживать» и «возобновлять» выполнение, подобно работе async/await, с ключевыми вызовами, такими как MoveNext() для перехода к следующему элементу, создавая эффективные итераторы и асинхронные потоки.
В этом и вся прелесть .Net. Если сначала Linq тормозил, то затем его оптимизировали. Это же касается и async/await
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, novitk, Вы писали:
N>·>Самый вменяемый код — это на Java N>Project Loom это конечно технически очень круто, но я не уверен, что .net надо подобное срочно пилить. Явная(async/await), а не скрытая, монада имеет свои преимущества.
Так CompletableFuture вроде есть, работает так же монадно, и не важно виртуальные треды или платформенные.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, SkyDance, Вы писали:
N>>Project Loom это конечно технически очень круто, но я не уверен, что .net надо подобное срочно пилить. SD>Надо, конечно, и в M$ это тоже понимают, просто это совсем не так легко, как кажется. Сделать Erlang из Java/C# занимает годы. https://github.com/dotnet/runtimelab/issues/2398
This issue is still useful as a summary of the experiment, but current efforts are now focused on Runtime-Async, so I'm going to close this issue and people can look at dotnet/runtime#109632 instead.
Здравствуйте, mrTwister, Вы писали:
T>Дальше не читал. Горутина в go — это просто структура данных. Как, например, Task в .net. Не в смысле, что это аналог, в смысле что это вспомогательная структура данных для организации вычислений. Вызов функции в go блокирует горутину точно так же, как await блокирует асинхронную функцию в C#
Если бы была возможность получить Task|Promise|Future не дожидаясь выполнения — то цены бы не было. А так все похерили — просто go не дает доступа к промису
Здравствуйте, Serginio1, Вы писали:
N>>а) WhenAll тут не нужен. S>Нужен. Он хочет параллельно выполнять 2 задачи. Хотя в .Net есть еще и Parallel.
Просто прогони код с двумя await и свой и убедись, что результат одинаков. await, как раз тот сахар, который тут доктор прописал. WhenAll нужен когда число Task не определенно.
S> Ну async/await сделан на основе Linq вернее yield в IEnumerable.
Я понимаю, что ты очень хочешь поделиться своими познаниями, но мы обзуждали разницу с jvm, а не на чьей основе он сделан.
S> В этом и вся прелесть .Net. Если сначала Linq тормозил, то затем его оптимизировали. Это же касается и async/await
Его некуда оптимизировать компилятором. Для реальных "green thread" нужно менять рантайм.
N>>>а) WhenAll тут не нужен. S>>Нужен. Он хочет параллельно выполнять 2 задачи. Хотя в .Net есть еще и Parallel. N>Просто прогони код с двумя await и свой и убедись, что результат одинаков. await, как раз тот сахар, который тут доктор прописал. WhenAll нужен когда число Task не определенно.
Согласен. Если сначала запустить 2 задачи а затем вызвать await будет одно и тоже.
WhenAll , что бы сократить код. Результат можно получить в цикле или нужно просто дождаться выполнение всех задач.
S>> Ну async/await сделан на основе Linq вернее yield в IEnumerable. N>Я понимаю, что ты очень хочешь поделиться своими познаниями, но мы обзуждали разницу с jvm, а не на чьей основе он сделан.
Эти зеленые потоки уже обсуждали множество раз. Там единственный плюс, что все выполняется в одном потоке, поэтому не нужны блокировки.
То же можно сделать и на C# со своим шедулером с одним потоком.
S>> В этом и вся прелесть .Net. Если сначала Linq тормозил, то затем его оптимизировали. Это же касается и async/await N>Его некуда оптимизировать компилятором. Для реальных "green thread" нужно менять рантайм.
Ну появились ValueTask, оптимизируются и шедулеры, оптимизируется и автомат переходов.
А green thread это вообще хрень.
В современных версиях Java, таких как Java 8 и выше, зелёные потоки не используются по умолчанию, и управление потоками передаётся операционной системе.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Shmj, Вы писали:
S>Здравствуйте, mrTwister, Вы писали:
T>>Дальше не читал. Горутина в go — это просто структура данных. Как, например, Task в .net. Не в смысле, что это аналог, в смысле что это вспомогательная структура данных для организации вычислений. Вызов функции в go блокирует горутину точно так же, как await блокирует асинхронную функцию в C#
S>Если бы была возможность получить Task|Promise|Future не дожидаясь выполнения — то цены бы не было. А так все похерили — просто go не дает доступа к промису
Ты чего удумал? Библиотеку комбинаторов создать на голанге? Гоферы не поймут!
Кстати, а как у тебя с хаскелем дела продвигаются? Не смотрел?
Эрланг, голанг и хаскель объединяет то, что во всех трех языках есть зеленые потоки (или их аналоги под другим маркетинговым брендом). Вот, когда есть такие потоки, то тогда разумно делать IO асинхронным внутри рантайма, причем с точки зрения программиста это становится прозрачным. Код IO программистом пишется как якобы синхронный, но исполняется он тогда как асинхронный на самом деле
Кстати, в хаскеле можно запустить асинхронное вычисление и получить аналог "Task|Promise|Future". В пакете async есть даже целый набор комбинаторов для этого. Более того, там даже есть такая штука, как асинхронные исключения, что как раз позволяет реализовать интересные комбинаторы с этими самыми "Task|Promise|Future". Например, можно запустить парочку другую асинхронных вычислений, дождаться первого завершивсегося, а остальные вычисления прибить за ненадобностью через такие исключения
Асинхронные исключения не пошли в серию, то есть, не пошли в мейнстрим, как не пошли рестарты в свое время из коммон-лиспа, но кое-что интересное с этими асинхронными исключениями получить можно (как и геморрой при обработке критических секций тоже)
Здравствуйте, Serginio1, Вы писали:
S>Эти зеленые потоки уже обсуждали множество раз. Там единственный плюс, что все выплняется в одном потоке, поэтому не нужна синхронизация.
зеленые потоки не выполняются в одном OS потоке и синхронизация нужна.
S>То же можно сделать и на C# со своим шедулером с одним потоком.
Бесшовно нельзя. Именно поэтому есть в C# Thread.Sleep и Таsk.Sleep, a в Го и jvm одна. Именно поэтому надо руками добавлять Task.Yield в числодробилки, а на Gо и jvm нет.
S>
S>В современных версиях Java, таких как Java 8 и выше, зелёные потоки не используются по умолчанию, и управление потоками передаётся операционной системе.
S>>В современных версиях Java, таких как Java 8 и выше, зелёные потоки не используются по умолчанию, и управление потоками передаётся операционной системе.
N>Что такое "по умолчанию"?
Чувак совершенно не в теме и порет чушь. Откуда-то выкопал цитату о "современных" версиях 25-летней давности про зелёные потоки, которые deprecated с версии 1.3. А тут идёт речь о Project Loom — это виртуальные потоки.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, mrTwister, Вы писали:
T>>>То есть функция начала работать на одном потоке ОС, а закончила на другом потоке. Как это возможно, если бы она не была асинхронной? T>·>Простите, но это уличная магия, а не асинхронность. Так работает шедулер и переключение контекста. После thread park (то что делает sleep) шедулер может продолжить исполнение на другом ядре. Это многопоточность, а не асинхронность. T>Шедулер может продолжить выполнение на другом ядре, а на другом потоке не может. Тут же выполнение происходит на другом потоке, а не ядре. Чтобы шедулер такое сделал функция обязана быть асинхронной и предоставлять промис для продолжения
Ты имеешь в виду шедулер ОС, а я имел в виду шедулер в рантайме Go. Обычная многопоточка, никакой асинхронности.
T>·>Асинхронный это если части кода выполняются одновременно. Примерно так, код, ясен пень, неработающий: T>Делается тривиальный хелпер на три строчки и код будет выглядеть точно так же
Ну т.е. создать новую функцию и передать всё через одно место (chan). И ещё каким-то хитровывернутым синтаксисом...
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай