Middle
Czym jest czas działania (runtime) i jak działa planista (scheduler)?
sobes.tech AI
Odpowiedź od AI
Środowisko wykonawcze (runtime) w Go to środowisko, w którym uruchamiane są programy Go. Obejmuje:
- Zarządzanie pamięcią: Kolektor śmieci (garbage collector) automatycznie zarządza przydziałem i zwalnianiem pamięci.
- Planista (scheduler): Zarządza wykonywaniem gorutyn na wątkach systemu operacyjnego.
- Wywołania systemowe: Zapewnia interfejs do interakcji z systemem operacyjnym.
- Prymitywy synchronizacji: Kanały, muteksy i inne mechanizmy do koordynacji gorutyn.
Planista Go implementuje model M:N (wiele gorutyn na wiele wątków systemu operacyjnego). Jego główne komponenty:
- G (Goroutine): Lekki wątek wykonawczy, zasadniczo abstrakcja nad funkcją.
- M (Machine): Wątek systemu operacyjnego, na którym uruchamiane są programy Go.
- P (Processor): Logiczny procesor powiązany z wątkiem OS. Przechowuje lokalną kolejkę
runnablegorutyn.
Zasada działania planisty:
- Gorutyny (G) są tworzone i dodawane do globalnej lub lokalnej kolejki
runnable. - Wątki OS (M) są powiązane z logicznymi procesorami (P). Liczba P domyślnie równa się liczbie rdzeni CPU (
GOMAXPROCS). - P pobiera gorutynę z własnej lokalnej kolejki. Jeśli kolejka lokalna jest pusta, P próbuje "ukraść" (steal) gorutyny z kolejki innego P lub z kolejki globalnej.
- M wykonuje gorutynę.
- Gdy gorutyna zostaje zablokowana (np. podczas odczytu z kanału bez danych lub wywołania systemowego), M odłącza się od P, a P staje się dostępny do wykonania innej gorutyny. Zablokowana gorutyna jest ustawiana w oczekiwaniu. Gdy blokada zostaje zdjęta, gorutyna ponownie staje się
runnablei wraca do kolejki. - Jeśli M zostaje zablokowane w wywołaniu systemowym, nie trzyma P. Może zostać utworzony nowy M lub użyty istniejący, aby P mógł kontynuować wykonywanie innych gorutyn.
To podejście pozwala efektywnie wykorzystywać zasoby procesora i łatwo skalować zadania równoległe, ukrywając złożoność zarządzania wątkami OS przed programistą.
// Przykład tworzenia gorutyny
func myFunc() {
// Kod gorutyny
}
func main() {
go myFunc() // Uruchomienie gorutyny
// Główna część programu kontynuuje wykonywanie równolegle
}