Middle
Какво е време за изпълнение (runtime) и как работи планировчикът (scheduler)?
sobes.tech AI
Отговор от AI
Времето за изпълнение (runtime) в Go е средата, в която се изпълняват програмите на Go. Тя включва:
- Управление на паметта: Събирачът на отпадъци (garbage collector) автоматично управлява разпределението и освобождаването на памет.
- Планировчик (scheduler): Управлява изпълнението на goroutine-ите върху нишки на операционната система.
- Системни извиквания: Предоставя интерфейс за взаимодействие с операционната система.
- Примитиви за синхронизация: Канали, мютекси и други механизми за координация на goroutine-ите.
Планировчикът на Go реализира модел M:N (множество goroutine-и върху множество нишки на ОС). Основните му компоненти:
- G (Goroutine): Лека нишка за изпълнение, по същество абстракция над функция.
- M (Machine): Нишка на операционната система, върху която се изпълняват програмите на Go.
- P (Processor): Логически процесор, свързан с нишка на ОС. Той държи локална опашка
runnableза goroutine-и.
Принцип на работа на планировчика:
- Goroutine-ите (G) се създават и добавят към глобална или локална опашка
runnable. - ОС нишките (M) се асоциират с логически процесори (P). Броят на P по подразбиране е равен на броя ядра CPU (
GOMAXPROCS). - P взема goroutine от своята локална опашка. Ако локалната опашка е празна, P се опитва да "краде" (steal) goroutine-и от опашката на друг P или от глобалната опашка.
- M изпълнява goroutine.
- Когато goroutine блокира (например, при четене от канал без данни или при системно извикване), M се отделя от P, и P става достъпен за изпълнение на друга goroutine. Блокираната goroutine се поставя в очакване. Когато блокирането бъде премахнато, goroutine-ът отново става
runnableи се връща в опашката. - Ако M блокира в системно извикване, той не държи P. Може да бъде създадено ново M или използвано съществуващо, за да може P да продължи изпълнението на други goroutine-и.
Този подход позволява ефективно използване на ресурсите на процесора и лесно мащабиране на паралелните задачи, като скрива сложността на управлението на нишките на ОС от разработчика.
// Пример за създаване на goroutine
func myFunc() {
// Код на goroutine
}
func main() {
go myFunc() // Стартиране на goroutine
// Основната програма продължава изпълнението си паралелно
}