122 lines
3.1 KiB
Text
122 lines
3.1 KiB
Text
@startuml gil_switching_mechanism
|
|
title GIL Switching - что происходит на микроуровне
|
|
|
|
participant "Event Loop\n(Main Thread)" as EL
|
|
participant "Python\nRuntime" as PY
|
|
participant "Worker Thread" as WT
|
|
participant "GIL" as GIL
|
|
participant "OS Kernel" as OS
|
|
|
|
== Запуск Worker Thread ==
|
|
|
|
EL -> WT: asyncio.to_thread(requests.get)
|
|
activate WT
|
|
|
|
note over EL #90EE90
|
|
Event Loop продолжает работать!
|
|
Ждёт своей очереди на GIL
|
|
end note
|
|
|
|
== Фаза 1: Worker Thread стартует (Python код) ==
|
|
|
|
WT -> GIL: Захватывает GIL
|
|
note over GIL #FFD700: Worker Thread держит GIL
|
|
|
|
WT -> WT: import requests
|
|
WT -> WT: подготовка параметров
|
|
WT -> WT: создание Request объекта
|
|
|
|
note over EL #FFD700
|
|
Event Loop ХОЧЕТ GIL,
|
|
но ждёт своей очереди
|
|
end note
|
|
|
|
PY -> PY: Прошло ~5ms или 100 bytecode инструкций
|
|
|
|
note over PY #90EE90
|
|
**GIL SWITCHING!**
|
|
Python runtime автоматически
|
|
переключает GIL между потоками
|
|
end note
|
|
|
|
PY -> WT: Отпусти GIL
|
|
WT -> GIL: Освобождает GIL (временно)
|
|
GIL -> EL: Захватывает GIL
|
|
|
|
note over EL #90EE90
|
|
Event Loop работает!
|
|
Обрабатывает задачи
|
|
end note
|
|
|
|
EL -> EL: await task1
|
|
EL -> EL: await task2
|
|
|
|
PY -> PY: Прошло ~5ms
|
|
|
|
PY -> EL: Отпусти GIL
|
|
EL -> GIL: Освобождает GIL
|
|
GIL -> WT: Захватывает GIL
|
|
|
|
note over WT
|
|
Worker Thread продолжает
|
|
подготовку к I/O
|
|
end note
|
|
|
|
== Фаза 2: Системный вызов (I/O) ==
|
|
|
|
WT -> WT: socket.connect()
|
|
note over WT #90EE90: Это системный вызов!
|
|
|
|
WT -> GIL: **Полностью освобождает GIL**
|
|
note over GIL #90EE90
|
|
🔓 GIL СВОБОДЕН!
|
|
Нет конкуренции
|
|
end note
|
|
|
|
WT -> OS: socket.recv() - ждёт данные
|
|
|
|
note over OS
|
|
Ядро читает данные
|
|
из сети
|
|
(секунды!)
|
|
end note
|
|
|
|
par Event Loop работает БЕЗ конкуренции
|
|
EL -> GIL: Захватывает GIL
|
|
EL -> EL: await task1 ✅
|
|
EL -> EL: await task2 ✅
|
|
EL -> EL: await task3 ✅
|
|
note over EL #90EE90
|
|
Полная скорость!
|
|
GIL не занят
|
|
end note
|
|
end
|
|
|
|
== Фаза 3: Данные получены ==
|
|
|
|
OS --> WT: Данные получены
|
|
WT -> GIL: Захватывает GIL опять
|
|
WT -> WT: обработка ответа (Python код)
|
|
|
|
note over WT,GIL #FFD700
|
|
Снова конкуренция за GIL
|
|
(но это быстро - десятки мс)
|
|
end note
|
|
|
|
PY -> PY: GIL switching работает
|
|
|
|
WT -> WT: возврат результата
|
|
WT --> EL: Результат готов
|
|
deactivate WT
|
|
|
|
note over EL,WT #90EE90
|
|
**Итого:**
|
|
- Фаза 1 (подготовка): ~10-50ms, GIL switching
|
|
- Фаза 2 (I/O): секунды, GIL свободен
|
|
- Фаза 3 (обработка): ~10-50ms, GIL switching
|
|
|
|
Основное время - I/O, где GIL свободен!
|
|
end note
|
|
|
|
@enduml
|
|
|