Здравствуйте, друзья! Сегодня разберем одну из самых интересных тем в
Swift: как работают протоколы на низком уровне. Если вы думаете, что протоколы это просто синтаксический сахар, приготовьтесь удивляться!
Что такое Existential Container:
Когда мы объявляем переменную с типом протокола:
var item: MyProtocol = MyStruct()
Компилятор создает специальную сущность:
Existential Container. Это коробка, которая хранит:
- Само значение.
- Метаданные о типе.
- Таблицу методов протокола.
Как устроена память:
На 64-битных системах
Existential Container занимает 40 байт (5 машинных слов):
- 24 байта - данные значения.
- 8 байт - указатель на метаданные типа (VWT).
- 8 байт - указатель на таблицу методов (PWT).
Inline vs Outline хранение:
Swift умный! Если ваша структура помещается в 24 байта, то данные хранятся прямо в буфере
Existential Container (inline):
struct MyStruct: MyProtocol {
let a: Int
let b: Int
let c: Int
}
Если данные больше 24 байт, то создается объект в куче и в буфер контейнера сохраняется только указатель на эту память (outline).
Value Witness Table (VWT):
Это «инструкция по эксплуатации» для типа.
VWT содержит функции:
- initialize - создание значения.
- copy - копирование.
- destroy - очистка памяти.
Для тривиальных типов (Int, Double) многие операции пустые заглушки!
Protocol Witness Table (PWT):
Вот где магия!
PWT связывает методы протокола с конкретными реализациями:
protocol Drawable {
func draw()
}
struct Circle: Drawable {
func draw() {
}
}
Компилятор создает таблицу, где
draw() указывает на реализацию в
Circle.
Где находятся VWT и PWT:
Value Witness Table (VWT) и
Protocol Witness Table (PWT) хранятся в сегменте данных программы - это статическая память, которая существует на протяжении всего времени жизни приложения.
- VWT создается для каждого типа на этапе компиляции.
- PWT создается для каждой пары «тип-протокол» на этапе компиляции.
- Existential Container содержит только указатели на эти таблицы.
Особенности Existential Container:
- Existential Container более ресурсоемкий чем Generic.
- Большие структуры хранятся в куче.
- Возможно менять типы в runtime.
Вывод:
Existential Container - это мощный механизм, но не бесплатный. Понимание его работы помогает писать более эффективный код.