Re[14]: Горутины и потоки
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 04.07.21 05:18
Оценка: 12 (1)
Здравствуйте, Serginio1, Вы писали:

N>>Так с точки зрения ОС что поможет тут осознать, когда можно переключать на другую нить вообще другого процесса, а когда лучше этого не делать, потому что захвачен важный лок (и даже в случае асинхронных локов это блокирует другие задачи)?

N>>Я б ожидал каких-то явных системных вызовов, но тут про них ни слова.
S>Ту тут главное tcs.TrySetResult(item);
S>И фцфше может продолжаться в этом же потоке в зависимости от условий создания TaskCompletionSource

Как по мне, это мало того, что имеет очень слабое отношение к теме дискуссии, так и вообще какое-то кошмарное безумие. На чём тут дедлочиться??
Ну, стал родитель в ожидание. Пошёл запускаться код из вложенной задачи. Ну поспал (Thread.Sleep асинхронный?) Поставил результат. Родитель проснулся. Что может пойти не так? Что за бардак там в дотнете, или C#, кто это строит?

Я вот хотел сделать (на Core 5.0) чтобы коллбэки на чтение сокета срабатывали всегда в нужной нитке. Не получается: мне их, фактически, принудительно загоняют в какой-то пул, который я не просил создавать, и я должен ещё думать о мьютексах, чтобы применить их данные. А тут, наоборот, какая-то самоблокировка на одной нитке непонятно на чём.

И при чём тут какой-то TrySetResult? Try на ожидание — я понимаю, а на SetResult — нет. Мы заданием результата для Task снижаем "напряжение" в системе, сокращая количество ожидаемых сущностей и сокращая contention за ресурсы (включая ожидания), тогда какой нафиг Try?

N>>Кто сбрасывается? Кэш процессора? Зачем? Даже с мерами против Meltdown/Spectre кэш сбрасывается при переключении между процессами, а не между нитками одного процесса. Хотя о чём и, главное, чем думают тут в MS, я не в курсе.


S>Ну кэш то первого уровня точто сбросится ибо слишком мал. И все зависит от используемых данных потока.


Он не _сбросится_. Он _вымоется_. Разница принципиальна. И почему ты думаешь, что они будут использовать настолько разные код и данные?

Я вон выше уже упоминал: открыл сокет, повесил коллбэки на приём датаграмм. Послал две датаграммы. Один коллбэк вызвался в нитке 6, другой — в нитке 9 (дотнет нумерует). Зачем?

S>>>У меня вопрос если все так прекрасно с переключением потоков, то зачем делают все, что бы отказаться от потоков и использовать очередь потоков?


N>>Кто сказал, что "всё прекрасно"? Я не знаю, откуда и как вы делаете такие выводы.

N>>И что это "все", что делают чтобы отказаться? В основном делают там, где просто неудобно/дорого по другим причинам возлагать это на ОС.
S>Асинхронность и производительность
S>Утверждают, что выхлоп есть

По сравнению с чем? Там сплошная Обстракция(tm) без конкретики.
Ну, повторюсь, на Windows треды дорогие (и создание, и переключение). Вероятно, по сравнению с этим, действительно, польза async-await очевидна.

N>>Да, есть цена на переключение, даже вход и выход из системного вызова чего-то стоит, и на Windows эта цена сильно выше, чем на Linux. Может, потому для Windows и стараются сократить эти переключения. В Linux я не вижу такого активного стремления, если где-то такое делают, то в рантаймах со сложной собственной логикой и полностью "управляемым" выполнением (Go, Erlang).


S> Ну сейчас практически все сервера в облаке на линуксе, но там же и asinc await используются на прополуюю ибо основная то работа это запрос к базе данных и прочие асинхронные операции


Возможно. А меряли результат по сравнению с другими подходами?

S>>>Если lock занят то возвращается Task и ожидается пока не вызовется SetResult

S>>>Никакой остановки потока нет. Да внутри конечно есть короткий lock который нужно заменять на SpinLock

N>>Почему это "нужно заменять"? Обычный lock настолько неэффективен?

S>Обычный lock может быть долгим и ожидать его могут тысячи потоков.

Эээ...
1. Если у кого-то на "обычном локе" тысячи ниток, то тут в первую очередь нужно менять весь дизайн (может быть, даже архитектуру, в обычном понимании).
Любые локи предназначены для малого количества конкурентов за их ресурс. Даже по количеству хартов — это уже много. До 4 — нормально. Если выше — надо думать разделять на разные локи. Если выше 8 — срочно думать.
2. Я уже описывал работу адаптивных мьютексов. Вначале, да, цикл сколько-то попыток захвата в стиле спинлока — чистым CAS (если нет видимой очереди). Если они не получились, тогда уже начинать более серьёзную машину — или через await, или через Lock() в ядре.
Но противопоставлять спинлоки мьютексам и говорить про "эффективность" spinlock по сравнению с мьютексом — это просто смешно.
Спинлок заведомо менее эффективен на длительных периодах и большом количестве конкурентов. Есть случаи, когда его использование неизбежно — когда шедулера более высокого порядка просто нет (в первую очередь это борьба в ядре за общие ресурсы между разными хартами). Но в остальных случаях его использовать — только ухудшать.

S>Ну вот я и хочу разобраться если переключение потоков так эффективно, то нахрена городить async await?


1. "Во-первых, это красиво" (tm). Линейное написание кода в разы проще цепочек коллбэков, неважно, в явном виде или на промисах.
Если программист не справляется без await, он будет писать линейно, но будут сплошные блокировки на синхронных операциях. Await позволяет использовать широкие ресурсы кодеров с реальным улучшением характеристик именно за счёт этого — меньше блокировок.

2. При высокой цене переключения между нитками внутреннее переключение (шедулером на границе awaitʼа) будет в разы дешевле переключения через ОС.
The God is real, unless declared integer.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.