Я хотел бы знать, что такое копирование при записи и для чего оно используется? Термин «массив копирования при записи» несколько раз упоминается в руководствах Sun JDK, но я не понял, что он означает.
источник
Я хотел бы знать, что такое копирование при записи и для чего оно используется? Термин «массив копирования при записи» несколько раз упоминается в руководствах Sun JDK, но я не понял, что он означает.
Я собирался написать свое собственное объяснение, но эта статья в Википедии в значительной степени подводит итог.
Вот основная концепция:
Копирование при записи (иногда называемое «COW») - это стратегия оптимизации, используемая в компьютерном программировании. Фундаментальная идея состоит в том, что если несколько вызывающих запрашивают ресурсы, которые изначально неотличимы, вы можете дать им указатели на один и тот же ресурс. Эта функция может поддерживаться до тех пор, пока вызывающий объект не попытается изменить свою «копию» ресурса, после чего будет создана настоящая частная копия, чтобы изменения не стали видимыми для всех остальных. Все это происходит прозрачно для вызывающих абонентов. Основное преимущество состоит в том, что, если вызывающий объект никогда не вносит никаких изменений, не нужно создавать личную копию.
Также вот пример общего использования COW:
Концепция COW также используется при обслуживании мгновенных снимков на серверах баз данных, таких как Microsoft SQL Server 2005. Мгновенные снимки сохраняют статическое представление базы данных, сохраняя копию данных до модификации при обновлении лежащих в основе данных. Мгновенные снимки используются для тестирования или отчетов, зависящих от момента, и не должны использоваться для замены резервных копий.
clone()
для реализацииfork()
- память родительского процесса ЗАКРЫВАЕТСЯ для дочернего.«Копировать при записи» означает более или менее то, на что это похоже: у всех есть одна общая копия одних и тех же данных до тех пор, пока они не будут записаны , а затем копия будет сделана. Обычно копирование при записи используется для решения проблем, связанных с параллелизмом. В ZFS , например, блоки данных на диске выделяются для копирования при записи; до тех пор, пока нет изменений, вы сохраняете исходные блоки; изменение изменило только затронутые блоки. Это означает, что выделяется минимальное количество новых блоков.
Эти изменения также обычно реализуются как транзакционные , т. Е. Они имеют свойства ACID . Это устраняет некоторые проблемы с параллелизмом, поскольку тогда вам гарантируется, что все обновления являются атомарными.
источник
A
. Процесс1
,2
,3
,4
каждый хочет сделать копию и начать читать его, в «копировании при записи» система ничего не копируется пока все еще читаютA
. Теперь процесс3
хочет внести изменения в свою копиюA
,3
теперь процесс фактически сделает копиюA
и создаст новый блок данных с именемB
. Процесс1
,2
,4
все еще читает блок -A
процесс3
в настоящее время чтенияB
.A
должен создавать новую копию. Если вы спрашиваете, что произойдет, если возникнет и изменится совершенно новый процесс,A
тогда мое объяснение не содержит достаточно подробностей для этого. Это будет зависеть от конкретной реализации и потребует знаний о том, как вы хотите, чтобы остальная часть реализации работала, например о блокировке файлов / данных и т. Д.Я не буду повторять один и тот же ответ о копировании при записи. Я думаю , что ответ Эндрю и ответ Чарли уже очень ясно. Я приведу вам пример из мира ОС, просто чтобы отметить, насколько широко используется эта концепция.
Мы можем использовать
fork()
илиvfork()
создать новый процесс. vfork следует концепции копирования при записи. Например, дочерний процесс, созданный vfork, будет совместно использовать данные и сегмент кода с родительским процессом. Это ускоряет время разветвления. Ожидается, что будет использоваться vfork, если вы выполняете exec, а затем vfork. Таким образом, vfork создаст дочерний процесс, который будет совместно использовать данные и сегмент кода со своим родительским процессом, но когда мы вызываем exec, он загрузит образ нового исполняемого файла в адресное пространство дочернего процесса.источник
vfork
НЕ использует КОРОВУ. Фактически, если ребенок что-то напишет, это может привести к неопределенному поведению, а не к копированию страниц !! На самом деле, можно сказать, что это в некоторой степени верно. COW действует как будтоvfork
что-то не модифицируется в общем пространстве!Еще один пример: Mercurial использует копирование при записи, чтобы сделать клонирование локальных репозиториев действительно «дешевой» операцией.
Принцип такой же, как и в других примерах, за исключением того, что вы говорите о физических файлах, а не об объектах в памяти. Изначально клон - это не дубликат, а жесткая ссылка на оригинал. Когда вы изменяете файлы в клоне, создаются копии, представляющие новую версию.
источник
Я нашел эту хорошую статью о zval в PHP, в которой также упоминается COW:
источник
Он также используется в Ruby «Enterprise Edition» как изящный способ экономии памяти.
источник
Хорошим примером является Git, который использует стратегию хранения больших двоичных объектов. Почему он использует хеши? Отчасти потому, что с ними легче выполнять различия, но также потому, что упрощает оптимизацию стратегии COW. Когда вы делаете новую фиксацию с несколькими изменениями файлов, подавляющее большинство объектов и деревьев не изменится. Следовательно, фиксация через различные указатели, состоящие из хэшей, будет ссылаться на группу объектов, которые уже существуют, что значительно уменьшит пространство для хранения, необходимое для хранения всей истории.
источник
Это концепция защиты памяти. В этом компиляторе создается дополнительная копия для изменения данных в дочернем элементе, и эти обновленные данные не отражаются в данных родителей.
источник
Ниже представлена реализация Python с копированием при записи (COW) с использованием шаблона проектирования декоратора . Ссылка на неизменяемый
Value
объект содержится в изменяемомCowValue
объекте (декораторе).CowValue
Объект передает все запросы на чтение к неизменномуValue
объекта и перехватывает все запросы на запись, создавая новый неизменныйValue
объект с правильным состоянием.CowValue
Объект должен быть неглубокий копироваться между переменными , чтобы позволить совместное использованиеValue
объекта.источник