写时复制#
写时复制是一种机制,可以简化索引 API 并通过尽可能避免复制来提高性能。 CoW 意味着任何以任何方式从另一个 DataFrame 或 Series 派生的 DataFrame 或 Series 始终表现为副本。 有关如何有效使用写时复制的说明,请参见 此处。
引用跟踪#
为了能够确定在写入 DataFrame 时是否需要进行复制,我们必须知道值是否与另一个 DataFrame 共享。 pandas 内部跟踪所有与另一个块共享值的 Blocks
,以便能够判断何时需要触发复制。 引用跟踪机制是在 Block 级实现的。
我们使用自定义引用跟踪器对象 BlockValuesRefs
,它跟踪每个块,其值彼此共享内存。 引用通过弱引用持有。 每个共享某些内存的块对都应该指向同一个 BlockValuesRefs
对象。 如果一个块超出范围,对该块的引用就会消失。 因此,引用跟踪器对象始终知道有多少块处于活动状态并共享内存。
当一个 DataFrame
或 Series
对象与另一个对象共享数据时,要求每个对象都有自己的 BlockManager 和 Block 对象。换句话说,一个 Block 实例(由 DataFrame 持有,不一定用于中间对象)应该始终仅被单个 DataFrame/Series 对象唯一使用。例如,当您想将同一个 Block 用于另一个对象时,可以使用 block.copy(deep=False)
创建 Block 实例的浅拷贝(这将创建一个具有相同底层值的新 Block 实例,并正确设置引用)。
在写入值之前,我们可以询问引用跟踪对象是否有另一个与我们共享数据的活动块。如果确实存在另一个活动块,我们可以触发复制操作。