Ответ
Да, можно вручную реализовать семантику Copy-on-Write для кастомной структуры, чтобы оптимизировать производительность при работе с большими значениями.
Принцип работы: Данные хранятся в ссылочном типе (классе), а копирование буфера происходит только при попытке его изменения (записи), если на него есть несколько ссылок.
Пример реализации:
struct MyCoWStruct {
// 1. Данные хранятся в приватном классе
private class Storage {
var data: [Int]
init(data: [Int]) { self.data = data }
}
// 2. Единственная ссылка на хранилище
private var storage: Storage
init(data: [Int]) {
storage = Storage(data: data)
}
// 3. Публичное свойство с логикой CoW
var elements: [Int] {
get { storage.data }
set {
// 4. Ключевая проверка: копируем только если хранилище разделяется
if !isKnownUniquelyReferenced(&storage) {
storage = Storage(data: storage.data)
}
storage.data = newValue
}
}
// 5. Мутирующий метод также должен проверять уникальность ссылки
mutating func append(_ value: Int) {
if !isKnownUniquelyReferenced(&storage) {
storage = Storage(data: storage.data)
}
storage.data.append(value)
}
}
// Использование
var cow1 = MyCoWStruct(data: [1, 2, 3])
var cow2 = cow1 // На этом этапе копирования данных НЕТ
cow2.append(4) // Тут срабатывает CoW: создается новый Storage для cow2
print(cow1.elements) // [1, 2, 3]
print(cow2.elements) // [1, 2, 3, 4]
Ключевые элементы:
isKnownUniquelyReferenced(&object)— проверяет, является ли ссылка на объект уникальной.- Все мутирующие операции должны начинаться с этой проверки.
- Стандартные типы Swift (
Array,Dictionary,String) уже используют CoW под капотом.
Ответ 18+ 🔞
Ага, слушай, вот это тема! Смотри, бывает же такое — у тебя здоровенная структура, как шкаф советский, и её туда-сюда копировать — это ж пиздец просто, производительность на ноль ебать. Так вот, можно сделать свою Copy-on-Write логику, это когда данные копируются только тогда, когда ты реально лезешь их менять, а не просто так, от нехуй делать.
Как это работает, блядь: Суть в том, что все твои жирные данные засовываются в ссылочный тип, в класс, понимаешь? А сама структура — это просто контейнер с одной ссылкой на эту хуйню. И когда ты делаешь присваивание, копируется только ссылка, а не тонны данных. А вот когда ты начинаешь писать в эту структуру — вот тут-то и проверяем: а не смотрит ли ещё кто-то на этот же буфер? Если да — тогда, ёпта, делаем полную копию, чтобы не наебать соседа.
Смотри, как это выглядит в коде, вротберунчик:
struct MyCoWStruct {
// 1. Прячем данные в приватный класс, как золото в сейф
private class Storage {
var data: [Int]
init(data: [Int]) { self.data = data }
}
// 2. У нас тут одна-единственная пиздюлина-ссылка на хранилище
private var storage: Storage
init(data: [Int]) {
storage = Storage(data: data)
}
// 3. Публичное свойство, где вся магия и происходит
var elements: [Int] {
get { storage.data }
set {
// 4. Вот она, проверка на уникальность! Если на хранилище смотрят больше одной пары глаз — копируем!
if !isKnownUniquelyReferenced(&storage) {
storage = Storage(data: storage.data)
}
storage.data = newValue
}
}
// 5. Любой метод, который меняет данные, должен начинаться с той же ебалы
mutating func append(_ value: Int) {
if !isKnownUniquelyReferenced(&storage) {
storage = Storage(data: storage.data)
}
storage.data.append(value)
}
}
// Пример использования, чтобы не быть мудаком
var cow1 = MyCoWStruct(data: [1, 2, 3])
var cow2 = cow1 // В этот момент — нихуя не копируется! Только ссылка.
cow2.append(4) // А вот тут — бац! Проверка, копирование, и только потом запись.
print(cow1.elements) // [1, 2, 3] — оригинал не тронут, красота!
print(cow2.elements) // [1, 2, 3, 4] — у копии своя жизнь.
На что смотреть, ёпта:
isKnownUniquelyReferenced(&object)— это наше всё. Функция, которая говорит: «Чувак, на этот объект больше никто не ссылается?». Если нет — можно смело мутить.- Любое действие, которое меняет внутреннее состояние, должно с неё начинаться. Иначе получишь не CoW, а какую-то общую помойку, где все друг другу портят данные.
- Кстати, стандартные штуки в Swift —
Array,Dictionary,String— они уже так и работают под капотом, хитрожопые. Но если тебе своё, кастомное, надо — вот тебе схема.