我正在尽可能快地连续运行该方法,并且越快越好,所以很明显,如果CGDataProviderCopyData()
实际上是逐字节复制数据,那么我认为必须有一种更快的方法来直接访问该数据。 ..它只是内存中的字节。任何人都知道是否CGDataProviderCopyData()
真的复制了数据?或者它只是创建一个指向现有数据的新指针?
2 回答
字节被复制。
在内部使用数据提供者的内容创建 CFData ( CFDataCreate )。CFDataCreate 函数总是制作一个副本。
任何人都知道 CGDataProviderCopyData() 是否真的复制了数据?或者它只是创建一个指向现有数据的新指针?
这些都是一样的。指针是内存地址;根据定义,如果您在两个地址有相同的数据,那么它在两个地方都是相同的数据,所以您必须复制它(从一个到另一个或从一个共同的来源复制到两个)。
所以,让我们相应地重申这个问题:
或者它只是复制现有的指针?
Quartz 不一定能做到这一点,因为数据提供者不一定提供现有的指针,因为它们可以实现为本质上基于流(顺序)的提供者。
那么直接访问提供商呢?即使是那些也不需要一个字节指针;提供商可能只是提供按需范围的访问。
但是如果它确实提供了一个字节指针呢?好吧,文档说:
CGDataProviderReleaseBytePointerCallback
在 Quartz 调用您的函数之前,您不得移动或修改提供程序数据。
因此,可以想象,Quartz 可以重用指针。但是如果你在释放数据ReleaseBytePointer
之前释放了数据提供者(导致你的回调被调用)呢?
如果 Quartz 实现了 CFData 或 NSData 的私有自定义子类,该子类实现错误或接管调用的工作,这仍然是安全的ReleaseBytePointer
,因此,如果您创建直接访问提供程序并从中创建 CFData 并释放提供程序,您仍然可以使用 CFData 对象。
但这是很多如果。他们可能只是创建了一个普通的旧(创建时字节复制)CFData,这使其成为一个有效的性能问题。
分析它,看看它给你带来了多大的痛苦。如果足够担心,那么您需要一些解决方案:
- 您可以只实现
ReleaseBytePointer
一个无操作(空函数体)并分别释放字节,确保在释放提供者和数据之后这样做。理论上,如果它使用原始字节指针并且 Quartz 没有实现自定义 CFData 子类,则可以防止字节从 CFData 下流出。有点毛。不幸的是,Apple 不能真正依赖你这样做,所以我怀疑它是否真的会有所帮助。 - 而是直接处理 NS/CFData。创建数据提供者只是为了将它传递给 Quartz,然后释放它并立即忘记它(不是自己拥有它)。
- 根据您的需要,您可能更喜欢将回调结构保存在实例变量中,并直接调用它们来复制部分数据。当然,如果此解决方案对您有用,那么无论如何您都不会遇到上述问题,因为您没有创建 here-you-can-have-my-bytes-pointer 直接访问数据提供程序。
的文档CGDataProviderCreateWithCFData
没有说明它是否返回直接访问数据提供者,因此如果这是您创建数据提供者的方式,您必须谨慎行事。