Runtime
Как устроен планировщик горутин в Go runtime?
Планировщик (
Scheduler
) в Go — это часть среды выполнения (runtime),
которая управляет выполнением горутин, распределяя их на потоки ОС.
Основные характеристики:
-
Модель планировщика:
-
Go использует модель M:N, где M горутин выполняются на N потоках ОС.
-
Позволяет эффективно использовать системные ресурсы, выполняя множество горутин на ограниченном количестве потоков.
-
-
Компоненты:
-
Goroutine (G): Легковесная единица выполнения, представляющая собой функцию, запускаемую параллельно.
-
Processor (P): Логический процессор, который выполняет горутины, управляет очередью готовых к выполнению горутин.
-
Machine (M): Операционный системный поток, который выполняет горутины.
-
-
Работа планировщика:
-
Создание: Новая горутина создается и помещается в очередь готовых горутин.
-
Выбор: Логический процессор (P) выбирает горутину из своей очереди для выполнения.
-
Исполнение: Поток ОС (M) выполняет выбранную горутину.
-
Блокировка: Если горутина блокируется, поток ОС (M) может взять другую горутину из очереди.
-
Пример:
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
runtime.GOMAXPROCS(2) // Установка числа логических процессоров
go func() {
for i := 0; i < 5; i++ {
fmt.Println("Goroutine 1:", i)
time.Sleep(100 * time.Millisecond)
}
}()
go func() {
for i := 0; i < 5; i++ {
fmt.Println("Goroutine 2:", i)
time.Sleep(100 * time.Millisecond)
}
}()
time.Sleep(1 * time.Second)
}
Планировщик в Go обеспечивает эффективное выполнение множества горутин на ограниченном количестве потоков ОС, используя модель M:N и логические процессоры для управления очередями горутин.
Что такое горутина (goroutine)?
Горутина — это легковесная единица выполнения, аналогичная потоку, но гораздо более дешёвая в создании и управлении.
Основные характеристики:
-
Легковесность:
- Горутины имеют меньший накладной расход по сравнению с потоками ОС, позволяя создавать тысячи горутин одновременно.
-
Создание:
-
Горутина создается с помощью ключевого слова
go, перед которым указывается вызов функции. -
Пример:
go func() { fmt.Println("Hello from goroutine") }()
-
-
Параллелизм и конкурентность:
- Горутины могут выполняться параллельно на нескольких процессорах или конкурентно на одном.
Пример:
package main
import (
"fmt"
"time"
)
func main() {
go func() {
fmt.Println("Hello from goroutine")
}()
time.Sleep(1 * time.Second) // Даем время горутине завершить выполнение
fmt.Println("Hello from main")
}
В чем отличие горутины от потока?
Отличие горутины от потока:
-
Легковесность:
-
Горутины: Горутины потребляют меньше ресурсов и быстрее создаются.
-
Потоки: Потоки ОС тяжелее, требуют больше памяти и времени на создание и переключение.
-
-
Управление:
-
Горутины: Управляются планировщиком Go на уровне пользовательского пространства.
-
Потоки: Управляются ядром операционной системы.
-
-
Модель выполнения:
-
Горутины: Используют модель M:N, где множество горутин выполняются на ограниченном числе потоков ОС.
-
Потоки: Каждый поток ОС является отдельной единицей выполнения на уровне ядра.
-
-
Память:
-
Горутины: Начальный стек горутины очень мал (~2 KB) и может динамически расти.
-
Потоки: Начальный стек потока ОС значительно больше (обычно несколько МБ).
-
Как устроены горутины, сколько памяти они занимают в стеке?
Горутины — легковесные единицы выполнения, управляемые планировщиком Go.
Основные характеристики:
-
Легковесность:
- Горутины потребляют меньше ресурсов по сравнению с потоками ОС.
-
Память:
-
Начальный стек: Горутины начинаются с очень малого начального стека, примерно 2 KB.
-
Динамическое расширение: Стек горутины может динамически расти и уменьшаться по мере необходимости.
-
-
Планировщик:
- Планировщик Go использует модель M:N, где множество горутин (M) выполняются на ограниченном числе потоков ОС (N).
Пример:
package main
import (
"fmt"
"time"
)
func main() {
go func() {
fmt.Println("Hello from goroutine")
}()
time.Sleep(1 * time.Second)
fmt.Println("Hello from main")
}
Горутины в Go занимают около 2 KB начального стека и могут динамически расширяться, что делает их легковесными и эффективными для выполнения параллельных задач.
Как планировщик Go управляет горутинами и вытесняет их?
Управление горутинами в Go:
-
Планировщик Go (
Scheduler): Управляет выполнением горутин. -
Тип многозадачности:
-
До Go 1.14 вытеснение в основном зависело от безопасных точек, например проверок при вызове функций.
-
В Go 1.14 добавлено асинхронное вытеснение горутин на поддерживаемых платформах, в том числе циклов без вызовов функций.
-
Что такое сборщик мусора (GC)?
Сборщик мусора освобождает память недостижимых объектов. Если программа сохраняет ненужные ссылки, GC не устранит такую утечку; освобождение файлов и соединений тоже требует явного управления ресурсами.
Основные характеристики:
-
Автоматическое управление памятью:
- Освобождает память объектов, недостижимых от корней графа ссылок.
-
Периодическая работа:
- Запускается периодически во время выполнения программы.
-
Минимизация пауз:
- Стремится минимизировать паузы в работе приложения для улучшения производительности.
Как работает сборщик мусора в Go?
Как работает сборщик мусора в Go:
-
Трассировка:
-
Mark Phase: Определяет все достижимые объекты, начиная с корневых ссылок (стек, глобальные переменные).
-
Sweep Phase: Освобождает память, занятую недостижимыми объектами.
-
-
Преэмптивная многозадачность:
- В Go 1.5 появился конкурентный сборщик мусора. Это изменение GC, а не версия введения асинхронного вытеснения горутин (Go 1.14).
-
Постепенная (Incremental) работа:
- Разделяет работу на маленькие части, чтобы избежать длительных пауз в работе приложения.
-
Конкурентная работа:
- Сборщик мусора работает одновременно с приложением, минимизируя время пауз и обеспечивая плавную работу.
Сборщик мусора в Go работает путем трассировки и освобождения памяти, используя конкурентные и постепенные методы для минимизации пауз и обеспечения высокой производительности.