Русский
Русский
English
Статистика
Реклама

Linked List Когда нужно писать свой Copy-on-write в iOS?

Я всегда думал: "А зачем нужно писать свой copy-on-write? Ведь круто, когда есть структуры и они такие быстрые, что всё делают за тебя."

Но все это не нужно, пока не начинаешь писать свои типы и не подсаживаешься на LinkedList'ы.

Что такое этот связанный список и какие у него преимущества?

Связанный список имеет несколько теоретических преимуществ по сравнению с вариантами непрерывного хранения, такими как Array:

  • Связанные списки имеют временную сложность O (1) для вставки первых элементов. Массивы же имеют временную сложность O (n).

  • Соответствие протоколам сбора Swift, таким как Sequence и Collection, предлагает множество полезных методов для довольно небольшого количества требований.

Связанный список (Linked List) - это последовательность элементов данных, в которой каждый элемент называется узлом (Node).

Есть два основных типа связанных списков:

Односвязные списки - это связанные списки, в которых каждый узел имеет ссылку только на следующий узел.

Двусвязные списки - это связанные списки, в которых каждый узел имеет ссылку на предыдущий и следующий узел.

Вам нужно отслеживать, где список начинается и где заканчивается. Обычно это делается с помощью указателей, называемых head и tail.

Вот так это всё выглядит:

public class Node<Value> {  public var value: Value  public var next: Node?      public init(value: Value, next: Node? = nil) {    self.value = value    self.next = next  }}public struct LinkedList<Value> {  public var head: Node<Value>?  public var tail: Node<Value>?    public init() {}  public var isEmpty: Bool { head == nil }}

Вау, прикольная структура данных! Она знает и предыдущий, и следующий элемент. Также в списке мы быстро можем добавить. Но есть проблема.

Так как наша Node'a является классом, а значит и reference type. Это значит, что для многих узлов у нас есть общая ячейка памяти и куча ссылок на них. Они могут расти и с большими размера за ними сложно наблюдать.

Как решить эту проблему? Поскольку LinkedList является структурой и поэтому должен использовать семантику значений. Внедрение своего COW решит эту проблему.

Сделать value type значений с помощью COW довольно просто. Прежде чем изменять содержимое связанного списка, вы хотим создать копию базового хранилища и обновить все ссылки (начальные и конечные) на новую копию.

private mutating func copyNodes() {  guard var oldNode = head else {      return  }  head = Node(value: oldNode.value)  var newNode = head    while let nextOldNode = oldNode.next {    newNode!.next = Node(value: nextOldNode.value)    newNode = newNode!.next    oldNode = nextOldNode  }  tail = newNode}

Этот метод заменит существующие узлы связанного списка вновь выделенными узлами с тем же значением. Здесь всё очень круто, кроме введения накладных расходов O (n) на каждый вызов изменения

Оптимизируем COW

Накладные расходы O (n) при каждом вызове изменения недопустимы.

Есть два пути, которые помогают решить эту проблему. Первый - избегать копирования, когда у узлов только один владелец.

isKnownUniquelyReferenced

В стандартной библиотеке Swift существует функция isKnownUniquelyReferenced. Эта функция может использоваться, чтобы определить, имеет ли объект ровно одну ссылку на него.

И если добавить в начало функции copyNodes() код, то копировать дальше не надо:

private mutating func copyNodes(returningCopyOf node:Node<Value>?) -> Node<Value>? {  guard !isKnownUniquelyReferenced(&head) else {return nil  }  guard var oldNode = head else {return nil}  head = Node(value: oldNode.value)  var newNode = head  var nodeCopy: Node<Value>?  while let nextOldNode = oldNode.next {    if oldNode === node {      nodeCopy = newNode    }    newNode!.next = Node(value: nextOldNode.value)    newNode = newNode!.next    oldNode = nextOldNode}  return nodeCopy}

Этот метод имеет много общего с предыдущей реализацией. Основное отличие состоит в том, что он вернет вновь скопированный узел на основе переданного параметра.

Таким образом Copy-on-write не является чем-то далеким и подкапотным. А вполне управляемым и понятным.

Источник: habr.com
К списку статей
Опубликовано: 01.01.2021 18:11:05
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Алгоритмы

Swift

Linkedlist

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru