Здравствуйте, 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.