问题标签 [copy-on-write]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
5430 浏览

linux - fork() 中的写时复制如何处理多个分叉?

根据维基百科(可能是错误的)

当发出 fork() 系统调用时,将创建与父进程对应的所有页面的副本,并由操作系统为子进程加载到单独的内存位置。但在某些情况下不需要这样做。考虑当孩子执行“exec”系统调用(用于从 C 程序中执行任何可执行文件)或在 fork() 之后很快退出的情况。当只需要子进程为父进程执行命令时,不需要复制父进程的页面,因为 exec 将调用它的进程的地址空间替换为要执行的命令。

在这种情况下,将使用一种称为写时复制 (COW) 的技术。使用这种技术,当发生分叉时,不会为子进程复制父进程的页面。相反,页面在子进程和父进程之间共享。每当进程(父进程或子进程)修改页面时,都会为执行修改的进程(父进程或子进程)单独制作该特定页面的单独副本。然后,此过程将使用新复制的页面,而不是在所有未来引用中共享的页面。另一个进程(没有修改共享页面的进程)继续使用页面的原始副本(现在不再共享)。这种技术被称为写时复制,因为当某些进程写入时页面被复制。

似乎当任何一个进程尝试写入页面时。页面的新副本被分配并分配给产生页面错误的进程。原始页面随后被标记为可写。

我的问题是:如果在任何进程尝试写入共享页面之前多次调用分叉会发生什么?

0 投票
1 回答
757 浏览

java - 修改 CopyOnWriteArraySet 时出现 UnsupportedOperationException

学习由 Maurice Naftalin、Philip Wadler 撰写的 Java Generics and Collection 书,我在 CopyOnWriteArraySet 部分停止,在学习时尝试练习以使其牢记在心,但是我遇到了一个问题,让我透露一下我的琐碎代码:

到目前为止,我的大脑所理解的是,每当修改发生时,都会CopyOnWriteArraySet使用新的更改创建一个新的后备数组,问题是,CopyOnWriteArraySet通过iterator()是在后备数组还是前数组上进行,如果说前数组方便的话,它对我来说听起来很合理,CopyOnWriteArraySet.remove()适用于前阵列,CopyOnWriteArraySet.iterator().remove()适用于后阵列,对吗?

任何闪存都非常感谢,谢谢大家。

0 投票
2 回答
1588 浏览

c++ - 安全地使用 auto_ptr 交换对象而不锁定在多线程环境中?

我在堆上分配了一些很少修改但需要快速读取访问的数据结构。一个示例是在堆上分配的结构,许多线程以只读方式非常频繁地访问该结构。auto_ptr需要定期重写此结构并避免锁定争用,重写它并快速与结构的新auto_ptr实例交换指针。

我从CopyOnWriteArrayListJava 中得到了这个想法,并希望在 C++ 中执行类似的性能。

0 投票
3 回答
10722 浏览

php - (字符串)是否“硬拷贝”一个字符串?

PHP 使用修改时复制系统。

$a = (string) $a;($a is a already string)是否修改和复制任何内容?


特别是,这是我的问题:

参数 1 是mixed/ 我想允许传递非字符串并将它们转换为字符串。
但有时这些字符串非常大。所以我想省略一个参数的复制,那已经是一个字符串。

我可以使用版本Foo还是必须使用版本Bar

0 投票
3 回答
1473 浏览

php - 通过引用传递(当变量可以改变,但不是必须的)

已经非常彻底地解释了,如果它们是技术原因,您只能在 PHP 中通过引用传递,因为 Copy-On-Write 基本上使性能等效。据我了解,如果它从未更改过,它永远不会复制对象。

但是,如果函数确实更改了变量,但您的代码不再使用它/不使用任何已更改的部分怎么办?是否更改原始代码对代码无关紧要。是的,PHP 优化器可能会考虑这种情况,但我没有理由相信它会这样做。

传递单个引用肯定会比复制一个巨大的数组或对象快得多。

那么这是通过引用传递的好情况吗?

例如,假设您传入一个 DomCrawler (只不过是一个大的 [html 格式化] 字符串,除了在这种特定情况下它是通过引用隐式传递的)。爬行一点并提取一些信息。在许多情况下,您不需要将 Crawler 重置为其原始位置,因为您根本不会再次使用它。另外,想象一下我们确实使用了 DOMCrawler,我们从中读取 URI。该函数没有改变这一点,所以通过引用或值传递仍然是等价的,但是通过引用传递不会明显更优化吗?我认为这种情况对于任何优化者来说都很难发现。

0 投票
2 回答
185 浏览

c++ - 通过指针获取装饰 char* 和 char const*:好的做法?

您好,我想就我做一个字符串类(如std::string)的想法向公众进行调查,该类具有能够处理客户端提供的缓冲区的功能。

你预见到的危险是什么?是经典的味道吗?等等

我的意思是这样的:

所以我预见了两种策略:这将允许修改acquire_RW或不修改字符。在任何非常量方法的情况下,以及必须扩展缓冲区的方法的情况下;它只会在此时分配和复制。acquire_ROextRORW

在某种程度上,my::string类型变成了类型的装饰器char*

当然要小心不要在装饰器作为客户要求留下之前释放外部缓冲区。

感谢您分享您的担忧

0 投票
1 回答
152 浏览

perl - 在 Perl 退出时避免只读 forked() RAM 分配

在 Perl 中,我生成了一个巨大的只读数据结构,然后fork().

这是为了在分叉时利用 RSS 页面上的 COW。它工作得非常好,但是当一个子进程退出时,它会在死亡之前从 itelf 分配所有 RAM。

有没有办法避免这种无用的分配?

这是显示该问题的示例 Perl 代码。

在示例vmstat输出中,我们可以看到它首先只分配了 100MiB,然后在第一次睡眠后它分配了一小段时间,然后全部释放。

注意:这似乎不是 Perl 版本特定的问题。当我测试 5.8.8、5.10.1 和 5.14.2 时,它们都表现出这种行为。

更新:

正如@choroba 在评论中所问的那样,我也尝试undef了数据结构,但似乎它在分配 RAM 时触发了内存接触。

您可以在第一个脚本的末尾添加以下代码段。

0 投票
2 回答
1373 浏览

c++ - 共享内存和写入时复制或右值引用以及移动语义?

通用容器(如 Qt 容器中的容器)的共享内存/写入时复制是否被 C++11 移动语义和右值引用所取代?

一个失败,另一个成功?或者它们是互补的而不是替代的?

0 投票
1 回答
1502 浏览

c++ - C ++中的写时复制指针对象

我试图按照这篇文章 http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Copy-on-write了解如何在 C++ 中实现写入时复制指针。问题是,它对我不起作用。

对象的症结在于重载解引用运算符 (*) 以进行后台复制,如果它应该返回一个非常量引用:

可悲的是,似乎只运行了第二个版本。C-outing 我指向的对象会创建一个副本,甚至执行类似的操作

导致detach()函数运行。

关于为什么它没有像宣传的那样工作的任何想法?

0 投票
0 回答
430 浏览

performance - PAGE_WRITECOPY windows 内存的性能

我需要在应用程序中实现撤消重做功能,该应用程序读取项目文件并进行一系列单独的事务来更改项目的内容。该项目可能有数百 MB 大。

我的想法是在写时复制(PAGE_WRITECOPY)内存机制的基础上实现undo-redo。我假设在事务结束后,应用程序可以访问已更改和未更改的页面,比较它们,识别更改的记录,将原始记录状态存储在专用的撤消堆栈中,释放创建的未更改页面并恢复写入- 更改页面的复制保护。我有两个问题:

  1. 我如何以及在哪里可以找到原始(未更改)页面的地址。

  2. 这种实现的期待性能?项目记录的中间大小是 cira 100 字节。如果一个事务更改了 3000 条记录,这可能涉及更改 100 个或更多 4K 物理页面。复制时写入内存的性能是否足以支持每一步中数百个物理页面的例行更改?