Здравствуйте, Serginio1, Вы писали:
S>>>·>Было мало кода, был простой код. Стало много сложного кода. Что ты хотел мне этим продемострировать? S>>>Угу был дермовый код с блокировками потоков и хранением переменных привязанных к потоку. S>·>Что в этом плохого? S> Ты серьезно? Проблема серверов в переключении потоков, на это тратится время.
Хорошо, но уже лучше.
Т.е. на самом деле-то не сам код дерьмо, а дерьмо в переключении потоков, на которое тратится время.
S>При использовании задач используется пул потоков, а задача представляет собой замыкание с автоматом переходов после выполнения задачи.
Вот и представь себе, что существуют такие потоки, на переключение которых не тратится время! Код перестанет быть дерьмовым с твоей точки зрения?
S>>>Стал неблокирующий потоки, при этом код внутри монитора может быть асинхронный и переменные привязанные к задаче. S>·>Чем это лучше? S> Ну во первых lock используется только внутри одного потока, при использовании асинхронного подхода нужно использовать SemaphoreSlim.
Ты, видимо, на какой-то другой вопрос ответил. Я спросил, чем лучше, а не где что нужно унутре использовать. Для меня как-то не очевидно, что нужда чего-то где-то делать является чем-то хорошим...
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ·, Вы писали:
S>>При использовании задач используется пул потоков, а задача представляет собой замыкание с автоматом переходов после выполнения задачи. ·>Вот и представь себе, что существуют такие потоки, на переключение которых не тратится время! Код перестанет быть дерьмовым с твоей точки зрения?
Виртуальные потоки это примитивный аналог задач.
S>>>>Стал неблокирующий потоки, при этом код внутри монитора может быть асинхронный и переменные привязанные к задаче. S>>·>Чем это лучше? S>> Ну во первых lock используется только внутри одного потока, при использовании асинхронного подхода нужно использовать SemaphoreSlim. ·>Ты, видимо, на какой-то другой вопрос ответил. Я спросил, чем лучше, а не где что нужно унутре использовать. Для меня как-то не очевидно, что нужда чего-то где-то делать является чем-то хорошим...
Еще раз ответь себе на вопросы про Task.WhenAll, Task.WhenAny, CancellationToken
И как ты аналог TaskCompletionSource (CompletableFuture) будешь использовать в виртуальных потоках.
Так у задач есть свойство IsCompleted. Например Task.FromResult возвращает результат и задача не прерывается.
Еще раз виртуальные потоки хороши для старого кода, а вот для нового кода с async/await c Task.WhenAll, Task.WhenAny, CancellationToken, TaskCompletionSource
дает больше возможностей.
Это как претензии к Delphi насчет begin end. В студии есть подсказка и написать await не проблема за то дает больше степеней свободы.
Здравствуйте, Serginio1, Вы писали:
S>·>Вот и представь себе, что существуют такие потоки, на переключение которых не тратится время! Код перестанет быть дерьмовым с твоей точки зрения? S> Виртуальные потоки это примитивный аналог задач.
В точности наоборот. Задачи — примитивный кривой костыль при отсутствии возможности использовать потоки без проблем с производительностью. Ты же это сам кодом продемонстрировал.
S>>>·>Чем это лучше? S>>> Ну во первых lock используется только внутри одного потока, при использовании асинхронного подхода нужно использовать SemaphoreSlim. S>·>Ты, видимо, на какой-то другой вопрос ответил. Я спросил, чем лучше, а не где что нужно унутре использовать. Для меня как-то не очевидно, что нужда чего-то где-то делать является чем-то хорошим... S> Еще раз ответь себе на вопросы про Task.WhenAll, Task.WhenAny,
CompletableFuture.allOf и CompletableFuture.anyOf
S> CancellationToken
thread.interrupt() или CompletableFuture.cancel. При этом не надо этот твой мусор везде таскать через параметры.
S>И как ты аналог TaskCompletionSource (CompletableFuture) будешь использовать в виртуальных потоках.
Ровно так же, как и в обычных. В этом и сила.
S>Так у задач есть свойство IsCompleted.
Future.isDone
S>Например Task.FromResult возвращает результат и задача не прерывается.
CompletableFuture.completedFuture
S> Еще раз виртуальные потоки хороши для старого кода, а вот
Они хороши для любого кода. Ты же сам это продемонстировал.
S>для нового кода с async/await c Task.WhenAll, Task.WhenAny, CancellationToken, TaskCompletionSource дает больше возможностей.
Как оказалось — не даёт.
S>Это как претензии к Delphi насчет begin end. В студии есть подсказка и написать await не проблема за то дает больше степеней свободы.
Ты просто в суть вникнуть не можешь, т.к. проблемы с чтением. Вот про CompletableFuture упомянул, но, очевидно, даже доку не открывал. Иначе бы не писал этот бред.
S>Много примеров ты найдешь здесь S>Использование асинхронного шаблона на основе задач
Зачем мне этот цирк... Мне работу работать надо, а не через обручи прыгать.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
import java.util.concurrent.*;
class Program{
public static void main(String[] args) {
System.out.println("Main thread started...");
int number = 5; // исходное число для вычисления факториала
// определяем задачу, которая вычисляет факториал
Callable<Integer> task = () -> {
int n = number; // копируем число, чтобы не изменять егоint result = 1;
while(n > 0) result *= n--;
return result; // возвращаем результат задачи
};
// определяем задачу, которая будет выполнена в будущемvar futureTask = new FutureTask<Integer>(task);
// создаем и запускаем потокvar t = new Thread(futureTask); // futureTask - это объект Runnable
t.start();
// здесь могут быть какие-либо другие операции метода main
// которые должны выполняться одновременно с futureTask
System.out.println("Main thread works...");
try{
// ожидаем выполнения задачи
Integer factorial = futureTask.get();
System.out.printf("factorial of %d is %d\n", number, factorial);
}
catch(Exception ex){
System.out.println(ex.getMessage());
}
System.out.println("Main thread finished...");
}
}
Или
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(task);
// передаем в thenAccept обратный вызов
future.thenAccept(result -> System.out.printf("factorial of %d is %d\n", number, result));
// future.thenAccept - не блокирует основной поток
// и одновременно мы можем выполнять в основном потоке некоторую работу
System.out.println("Main thread works...");
Thread.sleep(2000);
System.out.println("Main thread finished...");
На C# будет типа такого
Task<int> task= Task.Run(()=>
{
int n = number; // копируем число, чтобы не изменять егоint result = 1;
while(n > 0) result *= n--;
return result; // возвращаем результат задачи
};
// здесь могут быть какие-либо другие операции метода main
// которые должны выполняться одновременно с futureTasktry{
var res = await task; // или в синхронном варианте int res = task.Result;
}
catch(Exception ex){
Console.WriteLine(ex.ToString());
}
)
В JavaScript, под влиянием TypeScript пришли к тому, что await значительно лучше чем создание цепочек обратных вызовов
Здравствуйте, Serginio1, Вы писали:
S>Вот смотрю я на асинхронное программирование в Яве
Похвально. Ещё посмотри на Structured Concurrency
S> // передаем в thenAccept обратный вызов
Непонятно какое это отношение имеет к virtual threads и к сабжу.
S> В JavaScript, под влиянием TypeScript пришли к тому, что await значительно лучше чем создание цепочек обратных вызовов
Лучше, конечно. Но речь идёт про virtual threads. С ними не нужен ни await, ни цепочки обратных вызовов. Можно писать тупой синхронный код и выполнять на миллионах тредов.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Философ, Вы писали:
Ф>>>Можешь не отвечать. А, вот тебе ещё в догонку: сможешь сделать так, чтоб при указанных нагрузках не всё процессорное время сожрал GC? Ф>·>А причём тут сабж? Ф>Чем больше потоков — тем больше рутов, от которых пляшет GC.
Да, кстати. Подумалось... async создаёт task-объект со state machine на каждый вложенный вызов. А стеки в VT это просто ноды в куче для GC. И это просто стек вызовов, а не дополнительный объект со стейт-машиной. Т.е. теоретически это более эффективно с т.з. GC. Но замеры я не проводил, может разница и незначительна.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ·, Вы писали:
Ф>>Чем больше потоков — тем больше рутов, от которых пляшет GC. ·>Да, кстати. Подумалось... async создаёт task-объект со state machine на каждый вложенный вызов. А стеки в VT это просто ноды в куче для GC. И это просто стек вызовов, а не дополнительный объект со стейт-машиной. Т.е. теоретически это более эффективно с т.з. GC. Но замеры я не проводил, может разница и незначительна.
Чем обьект стек, отличается от обьекта стейт-машина с точки зрения GC?
Другое дело что "тем больше рутов, от которых пляшет GC" совершенно не расскрыто. Может и не больше. А может и больше, но это не значит, что оно медленней.
N>Чем обьект стек, отличается от обьекта стейт-машина с точки зрения GC?
Напомнило вот это: "исключения плохие, потому что медленные, поэтому вместо исключений мы будем использовать кортеж Result, в поле Error которого мы будем на каждом уровне добавлять информацию о месте пролета ошибки".
Здравствуйте, novitk, Вы писали:
N>·>Да, кстати. Подумалось... async создаёт task-объект со state machine на каждый вложенный вызов. А стеки в VT это просто ноды в куче для GC. И это просто стек вызовов, а не дополнительный объект со стейт-машиной. Т.е. теоретически это более эффективно с т.з. GC. Но замеры я не проводил, может разница и незначительна. N>Чем обьект стек, отличается от обьекта стейт-машина с точки зрения GC?
Стек выделяется чанками. Т.е. объектов будет гораздо меньше, даже для глубоких рекурсий. Вот правда рекурсия на async мне бы мозг сломала... как вообще такое отлаживать например...
Если я правильно понял, то размер чанков выбирается автомагически в зависимости от того как операции ввода-вывода расположены в коде и согласовано с работой GC. https://youtu.be/6nRS6UiN7X0
N>Другое дело что "тем больше рутов, от которых пляшет GC" совершенно не расскрыто. Может и не больше. А может и больше, но это не значит, что оно медленней.
Ну нету рутов в виртуальных потоках. Из jep 444: "Unlike platform thread stacks, virtual thread stacks are not GC roots. Thus the references they contain are not traversed in a stop-the-world pause by garbage collectors, such as G1, that perform concurrent heap scanning."
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ·, Вы писали:
N>>Другое дело что "тем больше рутов, от которых пляшет GC" совершенно не расскрыто. Может и не больше. А может и больше, но это не значит, что оно медленней. ·>Ну нету рутов в виртуальных потоках. Из jep 444: "Unlike platform thread stacks, virtual thread stacks are not GC roots. Thus the references they contain are not traversed in a stop-the-world pause by garbage collectors, such as G1, that perform concurrent heap scanning."
Ну так в жабе VT — это костыль из говна и палок поверх ForkJoinPool, рутам там и взяться неоткуда, хотя в VT до сих пор проблему с пиннигом потоков не решили (и они еще и не preemptive).
Здравствуйте, НепредставимыйПхы, Вы писали:
N>>>Другое дело что "тем больше рутов, от которых пляшет GC" совершенно не расскрыто. Может и не больше. А может и больше, но это не значит, что оно медленней. НП>·>Ну нету рутов в виртуальных потоках. Из jep 444: "Unlike platform thread stacks, virtual thread stacks are not GC roots. Thus the references they contain are not traversed in a stop-the-world pause by garbage collectors, such as G1, that perform concurrent heap scanning." НП>Ну так в жабе VT — это костыль из говна и палок поверх ForkJoinPool
Что в этом плохого? Чем это отличается от async|await?
НП>рутам там и взяться неоткуда, хотя в VT до сих пор проблему с пиннигом потоков не решили.
Какую именно проблему? И где эту же проблему решили?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ·, Вы писали:
·>Здравствуйте, НепредставимыйПхы, Вы писали:
N>>>>Другое дело что "тем больше рутов, от которых пляшет GC" совершенно не расскрыто. Может и не больше. А может и больше, но это не значит, что оно медленней. НП>>·>Ну нету рутов в виртуальных потоках. Из jep 444: "Unlike platform thread stacks, virtual thread stacks are not GC roots. Thus the references they contain are not traversed in a stop-the-world pause by garbage collectors, such as G1, that perform concurrent heap scanning." НП>>Ну так в жабе VT — это костыль из говна и палок поверх ForkJoinPool ·>Что в этом плохого? Чем это отличается от async|await?
Упоротого жавабоя вижу я в тебе, не тебя ли уже гоняли тряпкой по disruptor в треде го?
НП>>рутам там и взяться неоткуда, хотя в VT до сих пор проблему с пиннигом потоков не решили. ·>Какую именно проблему? И где эту же проблему решили?
Здравствуйте, НепредставимыйПхы, Вы писали:
НП>>>Ну так в жабе VT — это костыль из говна и палок поверх ForkJoinPool НП>·>Что в этом плохого? Чем это отличается от async|await? НП>Упоротого жавабоя вижу я в тебе, не тебя ли уже гоняли тряпкой по disruptor в треде го?
Перешел на личности. А по делу сказать нечего.
НП>>>рутам там и взяться неоткуда, хотя в VT до сих пор проблему с пиннигом потоков не решили. НП>·>Какую именно проблему? И где эту же проблему решили? НП>https://openjdk.org/jeps/491
Цитирую: "Status Closed / Delivered". Что сказать-то хотел?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ·, Вы писали:
НП>>·>Какую именно проблему? И где эту же проблему решили? НП>>https://openjdk.org/jeps/491 ·>Цитирую: "Status Closed / Delivered". Что сказать-то хотел?
Да тащемта сказал уже, что хотел: месяц назад закрыли проблему о который ты даже не знал до вчерашнего дня, воистину тяжела жизнь упоротого жавабоя.
Здравствуйте, НепредставимыйПхы, Вы писали:
НП>>>https://openjdk.org/jeps/491 НП>·>Цитирую: "Status Closed / Delivered". Что сказать-то хотел? НП>Да тащемта сказал уже, что хотел: месяц назад закрыли проблему о который ты даже не знал до вчерашнего дня, воистину
Вообще-то почти четыре месяца назад. Об этом я уже писал чуть выше
, три недели назад. Но ты же не читатель...
НП>тяжела жизнь упоротого жавабоя.
Тебя так интересует моя жизнь! Ох, я так рад, что это взаимно, сладенький.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Shmj, Вы писали:
S>Допустим, по умолчанию все функции сделать async, а компилятор уже сам оптимизирует.
В своё время много было разговоров про автоматический параллелизм. Тут и WLIV (привет Эльбрусу), и автоматическая векторизация, и много чего еще.
Но толком не смогли. Трудно компилятору угодать, когда выгоднее параллелить, а когда — последовательно исполнять. Параллелизм дорог и имеет смысл, когда операции достаточно долгие и при этом независимые.
В результате победил ручной параллелизм при наличии поддержки в среде исполнения/языке. Ну, чтобы не писать pthread_create() и т.п., а go func() или тот же async/await.
Здравствуйте, ·, Вы писали:
·>Здравствуйте, Serginio1, Вы писали:
S>>Вот смотрю я на асинхронное программирование в Яве ·>Похвально. Ещё посмотри на Structured Concurrency
·>
S>> // передаем в thenAccept обратный вызов
·>
·>Непонятно какое это отношение имеет к virtual threads и к сабжу.
S>> В JavaScript, под влиянием TypeScript пришли к тому, что await значительно лучше чем создание цепочек обратных вызовов ·>Лучше, конечно. Но речь идёт про virtual threads. С ними не нужен ни await, ни цепочки обратных вызовов. Можно писать тупой синхронный код и выполнять на миллионах тредов.
Речь вообще то идет про асинхронный код в общем. virtual threads не покрывает все возможные варианты. Я специально тебе вопросы задавал.
virtual threads хороши для переноса синхронного кода. Но когда мне нужно параллельно запустить несколько задач , скачать с нескольких ресурсов и продолжить после завершения всех скачанных или первого скачанного, то как мне помогут virtual threads?
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
S>virtual threads хороши для переноса синхронного кода. Но когда мне нужно параллельно запустить несколько задач , скачать с нескольких ресурсов и продолжить после завершения всех скачанных или первого скачанного, то как мне помогут virtual threads?
тебе же вежливо разжували, зачем дурачком прикидываться ? virtual threads помогут написать сам метод, не задумываясь о параллельности. большая разница на фоне .net, где нужно четко понимать что метод будет частью асинхронного кода и нужно очень внимательно следить, что бы не застопорить всю параллельность на какой-нить и/о ожидании.
S>>virtual threads хороши для переноса синхронного кода. Но когда мне нужно параллельно запустить несколько задач , скачать с нескольких ресурсов и продолжить после завершения всех скачанных или первого скачанного, то как мне помогут virtual threads?
Gt_>тебе же вежливо разжували, зачем дурачком прикидываться ? virtual threads помогут написать сам метод, не задумываясь о параллельности. большая разница на фоне .net, где нужно четко понимать что метод будет частью асинхронного кода и нужно очень внимательно следить, что бы не застопорить всю параллельность на какой-нить и/о ожидании.
Gt_ не читатель. Еще раз. virtual threads хороши для переноса синхронного кода. Всё!
А вот когда нам нужна параллельность они ну никак в Красную Гвардию не годятся.
Что касается .Net то помню в Windows Mobile были только асинхронные методы. Большинство используют асинхронные методы. Проблем с async/await ни у кого нет.
Что касается неправильного вызова, то есть варнинги и ошибки при компиляции.
Кстати а как virtual threads существуют с FutureTask?
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
S>>> В JavaScript, под влиянием TypeScript пришли к тому, что await значительно лучше чем создание цепочек обратных вызовов S>·>Лучше, конечно. Но речь идёт про virtual threads. С ними не нужен ни await, ни цепочки обратных вызовов. Можно писать тупой синхронный код и выполнять на миллионах тредов. S> Речь вообще то идет про асинхронный код в общем. virtual threads не покрывает все возможные варианты. Я специально тебе вопросы задавал.
А ответы-то прочитал?
S>virtual threads хороши для переноса синхронного кода. Но когда мне нужно параллельно запустить несколько задач , скачать с нескольких ресурсов и продолжить после завершения всех скачанных или первого скачанного, то как мне помогут virtual threads?
Ты, похоже, не понимаешь разницу между асинхронным и параллельным исполнением. Это ортогональные понятия.
Ты напишешь обычный синхронный код, который это всё сделает. В этом топике уже несколько раз пережевывалось, перечитай.
Например, для первого скачанного будет как-то так:
В случае шарпа тебе придётся завести пары методов downloadSomeData/downloadSomeDataAsync, download/downloadAsync и кучу копипасты.
Давай ещё с другой стороны попробую зайти. Вот тут ты написал: S>var res = await task; // или в синхронном варианте int res = task.Result;
Вот зачем этот выбор? Более того, если ты воткнёшь тут "await", это значит сам метод придётся объявить async. И, возможно, это будет интерфейсный метод, тогда все его имплементации тоже придётся переделывать в async (даже если они простые и без всякой многопоточки/io). И все места вызовов этого метода. И где-то выше по стеку придётся ещё воткнуть await.
Зачем это всё?! Почему нельзя просто всегда писать "int res = task.Result"?
Сабж?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай