Здравствуйте, netch80, Вы писали:
N>Здравствуйте, Serginio1, Вы писали:
N>>>И что? ОС всё равно должна будет сделать это рано или поздно, если задача сама не отдаёт управление. А если отдаёт, то зачем ОС принудительно переключать?
S>>То что желательно указать в какие моменты можно переключать. Например дождаться выполнения lock
N>Эээ... после выполнения захвата лока (речь об этом, да?) как раз лучше не отдавать управление, а сделать максимум действий во время захвата. А до него — если лок занят — то раз ждём, надо оповестить шедулер о том, что есть отличный повод запустить другую задачу.
Я как раз про то, что если lock короткий, то не стоит передавать управление на другой поток.
N>>>Нет, само по себе ничего из цитированного не является тут аргументом в сторону async/await. Там точно так же — если управление отдано явно, то шедулер не будет забирать насильно, а если нет, то заберёт — скорее всего, средствами ОС. Более того, если в момент переключения на входе или выходе await не будет явно сказано "а теперь подумайте, не переключить ли" соответствующим системным вызовом, то ОС не будет знать, когда там userland занимается переключением вокруг awaitʼа, и тоже переключит в непредсказуемый (и, возможно, неподходящий) момент.
S>> Ну как же не. Как раз проблема в большей степени это проблемы с Синхронизирующие примитивы ядра. Мьютексы, Семафоры, эвенты и т. д.
N>И в чём тут проблема?
https://ru.wikipedia.org/wiki/%D0%9F%D0%B5%D1%80%D0%B5%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BA%D0%BE%D0%BD%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%B0
Синхронизирующие примитивы ядра. Мьютексы, Семафоры и т. д. Это и есть основной источник проблем с производительностью. Недостаточно продуманная работа с синхронизирующими примитивами может приводить к десяткам тысяч, а в особо запущенных случаях — и к сотням тысяч переключений контекста в секунду. [источник не указан 2477 дней]
S>>Для примера в эпоху до async/await поток ждет выполнения асинхронной операции.
S>>async/await берет на себя сохранения данных внутри класса (стек не нужен) и строит автомат и тот же поток который выполнял данную задачу, запускает другую. Нет никаких переключений.
N>А что, вот эти все "берёт на себя сохранения данных внутри класса" и аналогичное восстановление, по-вашему, не переключение? А что оно такое тогда?
Там нет восстаеовления ибо данные хранятся в куче. Да должны закинуть this в регистр и вызвать MoveNext
S>> Не зря же используют SpinLock. Если бы стоимость переключения была не важна, то нафига он нужен?
N>Вот этот, да?
N>Действительно, стоимость переключения (любого — в том числе которого вы не замечаете цитатой выше) высока. Но при чём тут спинлоки?
N>Спинлок это очень специфичное средство, которое становится эффективным только при одновременном выполнении двух условий: 1) конкуренты за лок чаще находятся на разных физических исполнителях (железных тредах, harts) и 2) длительность возможной конкуренции относительно мала. Иначе трата процессора на кручение вокруг ячейки памяти в ожидании, пока в той появится заветный нолик, слишком велика — лучше таки переключиться.
N>Классический мьютекс ещё со времён Solaris поэтому делает N попыток захвата как спинлока (процессорной операцией типа CAS, LL/SC), а если не получилось — уходит в ядерный вызов. В Linux сделано (в futex) так же. Что в Windows, не знаю, облом докапываться до исходников. Но использовать SpinLock как аргумент в пользу дороговизны переключения — это, мягко говоря, странно.
S>>Зачем тогда async/await
N>С точки зрения логики управления выполнением — именно для тех случаев, когда шедулер узнал, что ответа для await сейчас нет и надо дать кому-то управление.
N>С точки зрения исходного кода — чтобы писать его максимально линейно.
Линейно то и раньше писали, только внутри были всякие евенты и остановка потока.
N>Переключений в нём, в идеале, столько же, сколько в аналогичном коде на коллбэках или промисах.
Ну в итоге то колбеки запускаются из пула потоков.
S>>Ну и замена всяких Lock на ManualResetValueTaskSource
S>>http://rsdn.org/forum/dotnet/8030645.1Автор: Serginio1
Дата: 16.06.21
S>> https://stackoverflow.com/questions/66387225/awaiting-a-single-net-event-with-a-valuetask
N>Я что-то не могу это раскурить. Какой смысл в его применении?
Смысл в том, что замена lock на lockAsync. То есть нет никакого ожидания потока
S>>Конечно зависит от длительности задач, но если задачи непродолжительные, то пул потоков может и не переключаться а выполнять очередь заданий.
N>Тоже не понимаю, при чём тут эта реплика.
В том, что с использованием пула потоков сводит к минимуму переключение потоков