写时复制#

写时复制是一种通过尽可能避免复制来简化索引API并提高性能的机制。CoW意味着任何以任何方式从另一个DataFrame或Series派生的对象总是表现得像一个副本。关于如何高效使用写时复制的解释可以在 这里 找到。

参考跟踪#

为了能够在写入 DataFrame 时确定是否需要进行复制,我们需要知道这些值是否与其他 DataFrame 共享。pandas 内部跟踪所有与另一个块共享值的 Blocks,以便能够在需要触发复制时告知。引用跟踪机制在 Block 级别实现。

我们使用一个自定义的引用跟踪对象,BlockValuesRefs,它跟踪每个块,这些块的值与其他块共享内存。引用通过弱引用保持。每个共享某些内存的块对应该指向同一个 BlockValuesRefs 对象。如果一个块超出作用域,对该块的引用就会消失。因此,引用跟踪对象总是知道有多少块是活动的并共享内存。

每当一个 DataFrameSeries 对象与其他对象共享数据时,要求每个对象都有自己的 BlockManager 和 Block 对象。因此,换句话说,一个 Block 实例(由 DataFrame 持有,不一定用于中间对象)应该始终唯一地用于单个 DataFrame/Series 对象。例如,当你想将同一个 Block 用于另一个对象时,可以使用 block.copy(deep=False) 创建 Block 实例的浅拷贝(这将创建一个具有相同底层值的新 Block 实例,并正确设置引用)。

我们可以在写入值之前询问引用跟踪对象是否还有另一个共享数据的块处于活动状态。如果确实还有另一个块处于活动状态,我们可以触发写前复制。