происходило в конкретные моменты (сборка мусора, запуск другой горутины и пр), но с версии 1.14 это уже неакутально? Якобы теперь переключение происходит в любой момент, если рантайм решил, что горутина выполняется слишком долго
Не совсем в любой момент
Да, не совсем правильно выразился. Не в любой момент, но теперь контекст переключается без привязки к конкретным событиям вроде запуска сборщика мусора и пр?
Это не точно, но в случае реальных потоков, переключением контекста занимается операционная система, и там свой планировщик.
Там с какой-то версии вытеснение горутин стало происходить не только на системных вызовах, но и при вызовах в стандартную библиотеку.
https://habr.com/ru/post/502506/ Вот тут написано, что почти в любой момент. Без привязки к конкретным вызовам
Да ну. Не написано там так. Там объясняется про безопасные точки вытеснения.
Очевидно, что при переходе на вытесняющую концепцию сигнал о вытеснении может застать нашу горутину в любом месте. Но авторы GO решили не уходить от safe-points, а объявить safe-points everywhere! Ну конечно, есть подвох, almost averywhere на самом то деле. Как говорилось выше, есть некоторые unsafe-points, где вытеснять мы никого не будем Вот же
Almost everywhere. Это форма речи.
Я всё равно не понимаю. В текущей версии планировщика обязательно будет переключение при, например, системном вызове или нет?
При системном вызове будет, разумеется. Чего же ещё делать приложению, когда оно вошло в ядро.
То есть просто в новой версии go добавили ещё одни safe pointer'ы, в которых возможно переключение контекста? И все старые точки оставлись?
Там все примерно так работает: - В определенных точках компилятор вставляет код, который выставляет флаг или семафор "можно прерываться". - Планировщик периодически вызывает isAsyncSafePoint, который этот флаг проверяет. Если он выставлен, тогда он забирает управление у горутины.
А как выглядят эти точки? И что там используется? Атомарные переменные?
Компилятор вставляет на стек переменную, через которую можно отслеживать состояние горутины, и в определенных участках кода вставляет вызовы, модифицирующие это состояние.
Вроде понял, спасибо
Надо будет задизасмить
Нашел в коде: компилятор проверяет буквально каждую ассемблерную инструкцию - и если она работает с регистром, который на конкретной архитектуре не сохраняется при переключении контекста, то добавляет код, который выставит состояние "небезопасная точка для вытеснения".
Обсуждают сегодня