写时复制#
写时复制(Copy on Write,CoW)是一种机制,旨在通过尽可能避免复制来简化索引 API 并提高性能。CoW 意味着任何以任何方式从另一个 DataFrame 或 Series 派生出的 DataFrame 或 Series 都将始终表现为副本。关于如何高效使用写时复制的解释可以在这里找到。
引用追踪#
为了能够确定在写入 DataFrame 时是否需要进行复制,我们必须了解其值是否与另一个 DataFrame 共享。pandas 内部会追踪所有与另一个块共享值的 Blocks
,以便在需要触发复制时做出判断。引用追踪机制是在块(Block)级别实现的。
我们使用一个自定义的引用追踪对象 BlockValuesRefs
,它追踪每个值相互共享内存的块。引用通过弱引用(weak-reference)持有。每对共享内存的块都应指向同一个 BlockValuesRefs
对象。如果一个块超出作用域,则对该块的引用将失效。因此,引用追踪对象始终知道有多少块是活跃的并共享内存。
无论何时 DataFrame
或 Series
对象与另一个对象共享数据,都需要每个对象拥有自己的 BlockManager 和 Block 对象。换句话说,一个 Block 实例(由 DataFrame 持有,不一定用于中间对象)应该始终唯一地用于单个 DataFrame/Series 对象。例如,当您想为另一个对象使用相同的 Block 时,您可以使用 block.copy(deep=False)
创建 Block 实例的浅拷贝(这将创建一个新的 Block 实例,其底层值相同,并正确设置引用)。
在写入值之前,我们可以询问引用追踪对象是否存在与我们共享数据的其他活跃块。如果确实存在其他活跃块,我们可以在写入之前触发一次复制。