Здравствуйте, netch80, Вы писали:
N>>>Да, проблема есть (хотя про "основной источник проблем с производительностью" тут загнули, случай он разный бывает). Но вы никак от этого не избавитесь ни шедулингом, ни переходом на await, пока вам потребуется ровно та же синхронизация.
S>> Я тебе привел пример аналога LockAsync. Поток ничего не ждет, а по событию запускается из пула потоков. Вот пример асинхронной очереди
S>>AsyncProducerConsumerCollection
S>>Просто привел пример с использованием ValueTask вместо Task
N>Так с точки зрения ОС что поможет тут осознать, когда можно переключать на другую нить вообще другого процесса, а когда лучше этого не делать, потому что захвачен важный лок (и даже в случае асинхронных локов это блокирует другие задачи)?
N>Я б ожидал каких-то явных системных вызовов, но тут про них ни слова.
Ту тут главное tcs.TrySetResult(item);
И фцфше может продолжаться в этом же потоке в зависимости от условий создания TaskCompletionSource
http://rsdn.org/forum/dotnet/7639144.1Автор: RushDevion
Дата: 20.01.20
var tcs = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
https://docs.microsoft.com/ru-ru/dotnet/api/system.threading.tasks.taskcreationoptions?view=net-5.0#System_Threading_Tasks_TaskCreationOptions_RunContinuationsAsynchronously
N>>>Если так, то та же цена реально размазана по остальной работе: с данными в куче всегда дороже работать, чем с данными на стеке или тем более в регистрах: аллокация, GC где-то после, разыменование указателей (спрятанных в ссылках дотнетов), заметно худшее кэширование, потому что в стеке данные сидят плотно, и наверняка ещё и пара сотен байт вершины стека в кэшах процессора.
S>> Угу который при переходе на новый поток сбрасывается.
N>Кто сбрасывается? Кэш процессора? Зачем? Даже с мерами против Meltdown/Spectre кэш сбрасывается при переключении между процессами, а не между нитками одного процесса. Хотя о чём и, главное, чем думают тут в MS, я не в курсе.
Ну кэш то первого уровня точто сбросится ибо слишком мал. И все зависит от используемых данных потока.
S>>У меня вопрос если все так прекрасно с переключением потоков, то зачем делают все, что бы отказаться от потоков и использовать очередь потоков?
N>Кто сказал, что "всё прекрасно"? Я не знаю, откуда и как вы делаете такие выводы.
N>И что это "все", что делают чтобы отказаться? В основном делают там, где просто неудобно/дорого по другим причинам возлагать это на ОС.
Асинхронность и производительность
Утверждают, что выхлоп есть
N>Да, есть цена на переключение, даже вход и выход из системного вызова чего-то стоит, и на Windows эта цена сильно выше, чем на Linux. Может, потому для Windows и стараются сократить эти переключения. В Linux я не вижу такого активного стремления, если где-то такое делают, то в рантаймах со сложной собственной логикой и полностью "управляемым" выполнением (Go, Erlang).
Ну сейчас практически все сервера в облаке на линуксе, но там же и asinc await используются на прополуюю ибо основная то работа это запрос к базе данных и прочие асинхронные операции
N>>>Не может быть квадратных кругов и круглых квадратов. Если с данными надо работать, то для этого нужен доступ к ним. Если нужен доступ, их надо прочитать из памяти и записать в память, с соответствующей ценой. Я бы предпочёл, чтобы компиляция хранила максимум в регистрах процессора, а что не помещается — максимум на стеке: не будет дурных потерь скорости. А если при этом само переключение формально дороже — тоже не страшно, записать компактно пару сотен байт и потом прочитать — эффективнее, чем размазывать их по десяткам кэш-строк.
S>>Ну класс если используешь Value типы тоже будут компактно расположены, а не валуе типы что на стеке, что не на нем все равно в куче
N>То есть в дотнет ещё не завезли escape analysis? (сомневаюсь)
S>>>>>>Конечно зависит от длительности задач, но если задачи непродолжительные, то пул потоков может и не переключаться а выполнять очередь заданий.
N>>>>>Тоже не понимаю, при чём тут эта реплика.
S>>>> В том, что с использованием пула потоков сводит к минимуму переключение потоков
N>>>Так не от желания конкретной задачи тут зависит, а от того, будет ли тот лок свободен.
S>>Вот ссылочка из предыдущего сообщения AsyncSemaphore
S>>Если lock занят то возвращается Task и ожидается пока не вызовется SetResult
S>>Никакой остановки потока нет. Да внутри конечно есть короткий lock который нужно заменять на SpinLock
N>Почему это "нужно заменять"? Обычный lock настолько неэффективен?
Обычный lock может быть долгим и ожидать его могут тысячи потоков.
Ну вот я и хочу разобраться если переключение потоков так эффективно, то нахрена городить async await?