我想将一个相当大的数据结构加载到一个进程中然后分叉,希望减少总内存消耗。 os.fork
将以这种方式工作还是复制Linux(RHEL)中的所有父进程?
答案 0 :(得分:15)
即使使用了COW,CPython也会使用引用计数并将引用计数存储在每个对象的标题中。因此,除非您不对该数据执行任何操作,否则您将很快对所讨论的内存进行虚假写入,这将迫使系统复制数据。把它传递给一个函数?这是另一个引用,INCREF
,写入COW的内存。将其存储在变量或对象属性中?相同。即使只是查找一个方法呢?同上。
由于各种原因,一些内置数据结构将其大部分数据与对象分开(例如,大多数集合)。如果这些最终出现在不同的页面上 - 或者COW所使用的任何粒度 - 你可能会幸运地获得这些。但是,从这样的集合引用的对象不是免除的 - 使用它操作它的引用计数是相同的。
此外,将共享一些数据,因为设计中没有对它进行写入(例如,本机CPython代码),以及fork
'进程未触及的某些对象可能共享(我老实说不确定;我认为循环GC不会写入对象)。但Python代码使用的Python对象几乎可以保证写入。类似的推理适用于PyPy,Jython,IronPython等(只是他们在对象标题中使用位而不是进行引用计数)但我无法保证所有可能的配置。
答案 1 :(得分:3)
如果您使用的是* nix系统,那么os.fork()
将使用系统的fork()
调用,至少在Linux的情况下,该调用是写时复制:
http://linux.die.net/man/2/fork
参见“注释”部分