Recent from talks
Nothing was collected or created yet.
Copy-on-write
View on Wikipedia
Copy-on-write (COW), also called implicit sharing[1] or shadowing,[2] is a resource-management technique[3] used in programming to manage shared data efficiently. Instead of copying data right away when multiple programs use it, the same data is shared between programs until one tries to modify it. If no changes are made, no private copy is created, saving resources.[3] A copy is only made when needed, ensuring each program has its own version when modifications occur. This technique is commonly applied to memory, files, and data structures.
In virtual memory management
[edit]Copy-on-write finds its main use in operating systems, sharing the physical memory of computers running multiple processes, in the implementation of the fork() system call. Typically, the new process does not modify any memory and immediately executes a new process, replacing the address space entirely. It would waste processor time and memory to copy all of the old process's memory during the fork only to immediately discard the copy.[4]
Copy-on-write can be implemented efficiently using the page table by marking certain pages of memory as read-only and keeping a count of the number of references to the page. When data is written to these pages, the operating-system kernel intercepts the write attempt and allocates a new physical page, initialized with the copy-on-write data, although the allocation can be skipped if there is only one reference. The kernel then updates the page table with the new (writable) page, decrements the number of references, and performs the write. The new allocation ensures that a change in the memory of one process is not visible in another's.[citation needed]
The copy-on-write technique can be extended to support efficient memory allocation by keeping one page of physical memory filled with zeros. When the memory is allocated, all the pages returned refer to the page of zeros and are all marked copy-on-write. This way, physical memory is not allocated for the process until data is written, allowing processes to reserve more virtual memory than physical memory and use memory sparsely, at the risk of running out of virtual address space. The combined algorithm is similar to demand paging.[3]
Copy-on-write pages are also used in the Linux kernel's same-page merging feature.[5]
In software
[edit]This section needs expansion. You can help by adding missing information. (October 2017) |
COW is also used in library, application, and system code.
Examples
[edit]The string class provided by the C++ standard library was specifically designed to allow copy-on-write implementations in the initial C++98 standard,[6] but not in the newer C++11 standard:[7]
std::string x("Hello");
std::string y = x; // x and y use the same buffer.
y += ", World!"; // Now y uses a different buffer; x still uses the same old buffer.
In the PHP programming language, all types except references are implemented as copy-on-write. For example, strings and arrays are passed by reference, but when modified, they are duplicated if they have non-zero reference counts. This allows them to act as value types without the performance problems of copying on assignment or making them immutable.[8]
In the Qt framework, many types are copy-on-write ("implicitly shared" in Qt's terms). Qt uses atomic compare-and-swap operations to increment or decrement the internal reference counter. Since the copies are cheap, Qt types can often be safely used by multiple threads without the need of locking mechanisms such as mutexes. The benefits of COW are thus valid in both single- and multithreaded systems.[9]
In Docker, a set of software for implementing operating-system level virtualization, docker images are built in a layered format, with lower layers being read-only and the upper layer available for editing. Creating a new image which shares the same base layers as another image does not copy the layers, but instead follows COW principles and allows the two images to share layers until one is edited.[10][11]
In computer storage
[edit]COW is used as the underlying mechanism in file systems like ZFS, Btrfs,[12] ReFS, and Bcachefs, as well as in logical volume management and database servers such as Microsoft SQL Server.
In traditional file systems, modifying a file overwrites the original data blocks in place. In a copy-on-write (COW) file system, the original blocks remain unchanged. When part of a file is modified, only the affected blocks are written to new locations, and metadata is updated to point to them, preserving the original version until it’s no longer needed. This approach enables features like snapshots, which capture the state of a file at a specific time without consuming much additional space. Snapshots typically store only the modified data and are kept close to the original. However, they are considered a weak form of incremental backup and cannot replace a full backup.[13]
In order to create and start new containers quickly, container engines doing OS-level virtualization often perform copy-on-write in storage, either block-level copy-on-write (as described above) or file-level copy-on-write.
Some but not all filesystems support file-level copy-on-write as part of union mounting,[14] including OverlayFS, aufs, GlusterFS, and UnionFS.
See also
[edit]- Allocate-on-flush
- Dirty COW – a computer security vulnerability for the Linux kernel
- Flyweight pattern
- Memory management
- Persistent data structure
- Wear leveling
References
[edit]- ^ "Implicit Sharing". Qt Project. Archived from the original on 8 February 2024. Retrieved 10 November 2023.
- ^ Rodeh, Ohad (1 February 2008). "B-Trees, Shadowing, and Clones" (PDF). ACM Transactions on Storage. 3 (4): 1. CiteSeerX 10.1.1.161.6863. doi:10.1145/1326542.1326544. S2CID 207166167. Archived from the original (PDF) on 2 January 2017. Retrieved 10 November 2023.
- ^ a b c Bovet, Daniel Pierre; Cesati, Marco (1 January 2002). Understanding the Linux Kernel. O'Reilly Media. p. 295. ISBN 9780596002138. Archived from the original on 15 September 2024. Retrieved 10 November 2023.
- ^ Silberschatz, Abraham; Galvin, Peter B.; Gagne, Greg (2018). Operating System Concepts (10th ed.). Wiley. pp. 120–123. ISBN 978-1119456339.
- ^ Abbas, Ali. "The Kernel Samepage Merging Process". alouche.net. Archived from the original on 8 August 2016. Retrieved 10 November 2023.
- ^ Meyers, Scott (2012). Effective STL. Addison-Wesley. pp. 64–65. ISBN 9780132979184.
- ^ "Concurrency Modifications to Basic String". Open Standards. Archived from the original on 10 November 2023. Retrieved 10 November 2023.
- ^ Pauli, Julien; Ferrara, Anthony; Popov, Nikita (2013). "Memory management". PhpInternalsBook.com. Archived from the original on 10 November 2023. Retrieved 10 November 2023.
- ^ "Threads and Implicitly Shared Classes". Qt Project. Archived from the original on 3 December 2023. Retrieved 10 November 2023.
- ^ "Storage drivers". Docker Documentation. 13 November 2025. Retrieved 23 November 2025.
- ^ Tiwari, Anjaneya (18 December 2024). "🔍 Understanding Docker Storage: Image Layers, Copy-on-Write, and How Data Changes Work". Medium. Retrieved 23 November 2025.
- ^ Kasampalis, Sakis (2010). "Copy-on-Write Based File Systems Performance Analysis and Implementation" (PDF). p. 19. Archived (PDF) from the original on 5 May 2024. Retrieved 10 November 2023.
- ^ Chien, Tim. "Snapshots Are NOT Backups". Oracle.com. Oracle. Archived from the original on 10 November 2023. Retrieved 10 November 2023.
- ^ Neil Brown. "Overlay Filesystem".
External links
[edit]- "A history of copy-on-write memory management". A keen grasp of the obvious. 21 January 2011. Retrieved 18 November 2024.
Copy-on-write
View on GrokipediaFundamentals
Definition and Core Concept
Copy-on-write (COW) is a resource-management technique in which multiple users or processes initially share a single copy of data or memory, with the copy being duplicated only when a modification is attempted by one party, thereby preserving the original for others. This approach optimizes resource usage by avoiding unnecessary duplications during read operations.[6][1] At its core, copy-on-write employs lazy copying to postpone the actual duplication of resources until necessary, typically detected via mechanisms like reference counting—which monitors the number of entities sharing the resource—or page protection flags that induce a fault upon write access, enforcing read-only sharing until divergence occurs. This ensures efficient shared read-only access among participants while granting exclusive write access to modifiers through writetime copying.[1] The technique originated in the 1970s within early time-sharing operating systems, such as TENEX for the PDP-10, where it facilitated sharing of large address space portions for procedures and data, creating private copies solely for modified pages. It has since been generalized as a broader programming pattern applicable beyond initial system contexts.[6]Mechanism of Operation
Copy-on-write (CoW) operates by initially allowing multiple entities, such as processes or threads, to share the same underlying resource, such as a memory page or data block, without immediate duplication.[7] This sharing is established by pointing all relevant references to the single shared instance, often tracked via reference counting to monitor the number of sharers.[8] The mechanism proceeds in distinct steps. First, upon creation of a new entity that requires access to the resource, the system configures shared access by mapping all participants to the original resource, avoiding any copy at this stage. Second, read operations are permitted directly on the shared resource without triggering any additional actions, as modifications are not involved. Third, when a write attempt occurs on the shared resource, the system detects this via a protection mechanism and intervenes to create a private copy for the modifying entity. Finally, the write is applied only to this new copy, while the original remains unchanged for other sharers; reference counts are updated to reflect the split, decrementing the count on the original and initializing a new count for the copy.[7][8] Technical enablers ensure enforcement of this lazy copying. Memory protection attributes, such as marking shared pages as read-only in page tables, trigger an exception or trap on write attempts, routing control to a handler that performs the copy. Alternatively, versioning metadata or flags in data structures can signal shared status and invoke copy logic without hardware traps.[7][8] A generic algorithm for CoW can be illustrated in pseudocode as follows:function access_resource(address, operation):
if operation == READ:
perform_read(address) // Direct access to shared resource
else: // WRITE
if is_shared(address):
new_page = allocate_page()
if new_page == NULL:
handle_allocation_failure() // e.g., fail the operation
else:
copy_page(original_page(address), new_page)
update_reference_count(original_page(address), decrement)
update_reference_count(new_page, initialize=1)
update_mapping(address, new_page)
mark_writable(new_page)
perform_write(new_page, data)
else:
perform_write(address, data)
function access_resource(address, operation):
if operation == READ:
perform_read(address) // Direct access to shared resource
else: // WRITE
if is_shared(address):
new_page = allocate_page()
if new_page == NULL:
handle_allocation_failure() // e.g., fail the operation
else:
copy_page(original_page(address), new_page)
update_reference_count(original_page(address), decrement)
update_reference_count(new_page, initialize=1)
update_mapping(address, new_page)
mark_writable(new_page)
perform_write(new_page, data)
else:
perform_write(address, data)
Benefits and Limitations
Advantages
Copy-on-write (CoW) enhances memory efficiency by permitting multiple processes or entities to share the same physical memory pages initially, thereby avoiding redundant allocations and minimizing the overall memory footprint. Only when a write operation occurs on a shared page does the system create a private copy, ensuring that unmodified data remains shared across all users. This mechanism is especially advantageous for read-heavy workloads, where the write fraction is low—such as in applications where less than 50% of memory is modified—leading to substantial reductions in memory usage compared to immediate full copying approaches.[1] The technique delivers performance benefits by accelerating initial sharing operations, which support zero-copy reads from the common resource without any duplication overhead. By deferring the costly copy process until an actual write is detected, CoW improves system responsiveness and reduces latency in scenarios involving frequent sharing or cloning, as the expensive memory allocation and copying are postponed. This aligns briefly with lazy allocation principles, where resources are provisioned only as needed.[10] CoW embodies an effective space-time trade-off, balancing storage savings with deferred computational costs. Quantitatively, for N sharers of a resource of original size S and a write fraction of M%, the approximate space saved is (1 - M/100) × S × (N-1), since only the modified portions are duplicated per additional sharer. Empirical studies confirm this: in Franz Lisp, a 23% write fraction yields high sharing efficiency, while GNU Emacs at ~35% still achieves notable savings relative to full copies.[1] Additionally, CoW enables scalability in multi-user or multi-process environments by supporting efficient cloning, which limits resource proliferation and lowers aggregate system load through persistent sharing of unchanged data.[11]Disadvantages and Trade-offs
Copy-on-write mechanisms impose significant overhead on write operations, as modifying shared data necessitates duplicating the affected portions before alteration, which incurs latency from allocation and copying processes. This duplication temporarily doubles memory usage for the involved data structures, potentially straining resources in systems with limited memory availability. For instance, in virtual memory contexts, the copy operation during a page fault can amplify this cost, especially for large pages or frequent modifications. Repeated partial copies inherent to copy-on-write can lead to scattered memory allocations, fostering external fragmentation where free memory becomes fragmented into non-contiguous blocks that hinder efficient allocation of larger contiguous regions. This fragmentation complicates memory management, as coalescing scattered free space becomes more resource-intensive over time, reducing overall system efficiency. Implementing copy-on-write demands sophisticated tracking, such as reference counts or copy-on-write flags, to monitor sharing and trigger duplications appropriately, thereby elevating code complexity and maintenance burdens. This added intricacy heightens the risk of bugs, including race conditions in concurrent settings or mishandled sharing states, as evidenced by documented vulnerabilities in operating system kernels over the past decades. Reference counting pitfalls, such as non-atomic updates leading to incorrect sharing detection, further compound these implementation challenges.[12] Copy-on-write is particularly disadvantageous in write-heavy scenarios, where the frequent copying overhead outweighs read-time benefits, potentially degrading performance compared to immediate full copies. Trade-off analysis through workload characterization—assessing read-write ratios and access patterns—is crucial to determine suitability, as aggressive use in mutation-dominated environments can lead to excessive resource consumption.[13]Applications in Operating Systems
Virtual Memory Management
In virtual memory management, copy-on-write (CoW) integrates with paging by marking shared physical pages as read-only in the page tables of multiple processes, allowing initial sharing without immediate duplication. When a process attempts to write to such a page, the memory management unit (MMU) triggers a page fault, which the kernel's page fault handler intercepts to implement CoW: it allocates a new physical page, copies the original content, updates the faulting process's page table to point to the new page with write permissions, and leaves the original page unchanged for other sharers. This mechanism leverages the hardware's protection features to enforce sharing while ensuring isolation upon modification.[14] At the kernel level, CoW relies on page table entries (PTEs) configured with read-only permissions and reference counting on physical pages to track sharing; some systems use dedicated CoW bits in PTEs to flag shared writable mappings, while others, like Linux, achieve the effect through read-only marking and kernel-managed counters in the page struct. Upon a write fault, the handler verifies the sharing status, performs the copy if needed, and propagates updates only to the affected process's mappings without altering others, ensuring consistency across shared regions. In Windows, the kernel memory manager supports CoW through section objects marked with PAGE_WRITECOPY protection, integrating with its hierarchical page tables to handle faults similarly.[15][16] CoW promotes resource conservation by enabling multiple processes to map the same physical pages at startup, deferring allocation until writes occur, which significantly reduces RAM usage in multitasking environments where processes often share code or data segments without modification. For instance, in systems with frequent process creation, this lazy approach minimizes initial memory footprint, as only modified pages consume additional physical memory.[2][14] The technique evolved from early implementations like TENEX in the early 1970s, which supported CoW for mapped file pages to enable efficient sharing. It gained prominence in VAX/VMS starting in 1978, where it was used for process creation and library sharing to optimize virtual memory under hardware constraints of the era. Today, CoW is a standard feature in modern kernels, including Linux since its inception for efficient paging and Windows for shared memory sections.[17][18][14][16]Process Forking and Cloning
In Unix-like operating systems adhering to POSIX standards, thefork() system call creates a new child process by duplicating the parent process's address space using copy-on-write (CoW). Initially, the child shares the parent's physical memory pages, with the page table entries marked as read-only to detect modifications; upon a write attempt by either process, the kernel copies the affected page, allocating private copies for each.[2] This approach ensures the child starts with an identical virtual memory layout without immediate full duplication, optimizing resource use in multitasking environments.[19]
The CoW mechanism for fork() emerged in 4.3BSD (1986) as part of virtual memory advancements in Berkeley Software Distribution (BSD) Unix, building on earlier paging systems introduced around 1979 but initially lacking efficient duplication.[1][3] Prior implementations, such as in Research Unix Version 7, relied on full address space copying, which was costly for larger processes; CoW addressed this by deferring copies until necessary, significantly reducing setup overhead. In practice, this transforms the time complexity of memory setup from O(n—where n is the process size—to nearly O(1), as only page tables are duplicated upfront, with actual copying handled lazily via page faults.[20] For example, in scenarios where the child immediately calls exec() to load a new program, minimal or no pages are copied, avoiding unnecessary overhead.[1]
Variants of process cloning extend this efficiency in modern kernels. In Linux, the clone() system call generalizes fork() by allowing fine-grained control over shared resources via flags; without the CLONE_VM flag, it employs CoW for the virtual memory area (VMA), duplicating page tables while sharing physical pages until writes occur.[21] Similarly, Windows supports CoW through memory protection attributes in process creation and section mappings; the CreateProcess API, when using file-backed sections with PAGE_WRITECOPY, enables shared read access that forks private copies on modification, akin to Unix semantics for optimizing multiprocess scenarios.[22]
Edge cases during forking highlight CoW's nuances, particularly with shared resources. Shared libraries and memory-mapped files, typically loaded with read-only or shared mappings (e.g., via mmap with MAP_SHARED), remain physically shared across parent and child without triggering copies, as writes are prohibited or redirected to the underlying file.[2] Private mappings (e.g., MAP_PRIVATE) follow standard CoW, copying on write to preserve isolation. The subsequent exec() call disrupts this by unmapping the original address space and loading a new executable, effectively nullifying any pending CoW setup and preventing shared library inheritance from the parent.[1]
Applications in Software Development
Data Structure Optimization
Copy-on-write (CoW) techniques optimize data structures in user-space software by enabling efficient sharing of immutable or shared objects, particularly in collections like arrays, lists, and trees. In persistent data structures, mutations create new versions that share unchanged portions with the original, avoiding full copies and reducing memory overhead. This approach is foundational in functional programming paradigms, where data immutability ensures thread safety and versioned histories without explicit locking. Seminal work on purely functional data structures highlights how CoW-like sharing allows operations to achieve logarithmic time complexity for updates by copying only affected paths.[23] The synergy between CoW and immutability is evident in functional languages, where data structures maintain multiple versions through structural sharing. For instance, in a binary search tree, an update to a specific node requires copying the path from the root to that node, while unmodified subtrees remain shared across versions. This path-copying mechanism preserves the original tree intact, enabling efficient branching for operations like undo or versioning in algorithms. Such patterns minimize allocation costs, making them suitable for applications requiring historical data retention without proportional memory growth.[23] Reference-counted buffers exemplify CoW memory patterns for strings and similar sequential data, where multiple references point to a shared buffer until a mutation triggers a private copy. This defers copying until necessary, optimizing for scenarios with frequent reads and infrequent writes, such as string concatenation in libraries. The reference count tracks sharing, ensuring mutations isolate changes without affecting other users.[24] Adoption trends reflect CoW's integration into modern languages for data structure efficiency. In Rust, theCow<T> type implements clone-on-write semantics, allowing borrowed data to be accessed immutably and cloned lazily only on mutation, thus supporting zero-cost abstractions in generic code. Similarly, Java's CopyOnWriteArrayList, introduced in JDK 5, applies CoW to concurrent collections by replicating the entire array on writes, which eliminates locks for readers and prevents concurrent modification exceptions in high-read environments. These implementations underscore CoW's role in balancing performance and safety in shared data scenarios.[25][26]
Language and Library Examples
In C++, copy-on-write mechanisms are commonly implemented using reference counting, often with smart pointers likestd::shared_ptr to manage shared data buffers for efficiency in custom classes such as strings. This approach allows multiple instances to share the underlying data until a modification triggers a private copy, reducing memory allocation for read-only accesses.[27]
A prominent example is the Qt library's QString class, which employs implicit sharing with copy-on-write semantics. In this design, QString objects contain a pointer to a shared data structure that includes a reference count; assignment or passing by value performs a shallow copy by incrementing the count, while any write operation checks the count and detaches by copying the data if it exceeds 1.[28] This optimization was particularly beneficial for GUI applications handling frequent string copies without modifications.[29]
In Python, immutable types such as tuples facilitate structure sharing across references, effectively providing implicit copy-on-write behavior since "copies" reuse the same memory until an attempt to modify would create a new object. The sys.getrefcount() function reveals these shared references by returning the count of pointers to the object, which is typically higher than expected due to the caller's temporary reference during execution.[30] The pandas library implements explicit copy-on-write for its DataFrame and Series objects, allowing multiple references to share the underlying data until a mutation, at which point a private copy is created to maintain isolation. This enhances performance in data analysis workflows with frequent reads and occasional updates.[5]
Lisp languages, such as Common Lisp, leverage cons cells for efficient data sharing in lists and trees, allowing substructures to be referenced multiply without duplication, akin to the sharing phase of copy-on-write. A cons cell, representing an ordered pair with car and cdr pointers, enables persistent data structures where modifications to one shared part do not propagate unless explicitly intended, supporting functional programming patterns.[31] For instance, functions like copy-list create new cons cells for the top-level structure while sharing unchanged tails.[32]
In Go, strings are immutable views over byte slices, inherently supporting sharing without copy-on-write since modifications always produce new strings. Slices, however, offer copy-on-write potential through their shared backing arrays; operations like slicing create lightweight views that share data until an append or explicit copy reallocates a private buffer.[33] The built-in copy() function facilitates deep copies when needed, ensuring modifications do not affect shared sources.[33]
