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