CGDataProviderCopyData()实际上是否复制了字节?或只是指针?

时间:2010-04-30 13:01:57

标签: iphone performance core-graphics bytebuffer

我尽可能快地连续运行该方法,并且越快越好,所以很明显,如果CGDataProviderCopyData()实际上是逐字节地复制数据,那么我认为必须有更快的方式来直接访问该数据......它只是内存中的字节数。任何人都确定CGDataProviderCopyData()是否实际复制了数据?或者它只是创建一个指向现有数据的新指针?

2 个答案:

答案 0 :(得分:6)

复制字节。

在内部创建CFData(CFDataCreate),其中包含数据提供者的内容。 CFDataCreate函数总是复制。

答案 1 :(得分:5)

  

任何人都知道CGDataProviderCopyData()是否实际复制数据?或者它只是创建一个指向现有数据的新指针?

这些都是一样的。指针是内存地址;根据定义,如果您在两个地址具有相同的数据 ,则它在两个地方中是相同的数据,因此您必须将其复制(从一个到另一个或来自共同的起源)。

所以,让我们重申一下这个问题:

  

或者只是复制现有的指针?

Quartz不一定能做到这一点,因为data providers do not necessarily provide an existing pointer,因为它们可以实现为基本上基于流的(顺序)提供者。

直接访问提供商怎么样? Even those need not cough up a byte pointer;提供商可能只是简单地提供range-on-demand access

但是如果它确实提供了一个字节指针呢?好吧,the documentation for that说:

  

在Quartz调用CGDataProviderReleaseBytePointerCallback函数之前,您不得移动或修改提供者数据。

因此,可以想象,Quartz可以重用指针。但是,如果您在发布数据之前释放数据提供程序(导致调用ReleaseBytePointer回调)会怎样?

如果Quartz实现了CFData或NSData的私有自定义子类,它实现了错误或接管了调用ReleaseBytePointer的工作,那么这仍然是安全的,这样如果你创建一个直接访问提供者并创建一个CFData从它和发布提供程序,您仍然可以使用CFData对象。

但那是很多ifs。他们可能只是创建一个普通的旧(创建时字节复制)CFData,这使它成为一个有效的性能问题。

对其进行描述并查看它给您带来的痛苦程度。如果它足以让人担心,那么你需要一些解决方案:

  • 您可以将ReleaseBytePointer实现为无操作(空函数体)并单独释放字节,确保在释放提供者和数据后执行此操作。理论上,如果使用原始字节指针并且Quartz没有实现自定义CFData子类,则防止字节从CFData下消失。有点毛茸茸的。不幸的是,Apple无法真正依赖你这样做,所以我怀疑它实际上会有所帮助。
  • 直接处理NS / CFData。创建数据提供程序只是为了将它传递给Quartz,并释放它并在此后立即忘记它(不是自己拥有它)。
  • 根据您的需要,您可能更愿意将回调结构保留在实例变量中,并直接调用它们来复制部分数据。当然,如果这个解决方案适合你,那么你就不会遇到上面描述的问题,因为你不是在创建一个你可以拥有my-bytes-pointer的直接访问数据提供者。

CGDataProviderCreateWithCFData的文档没有说明它是否返回直接访问数据提供者,因此如果您正在创建数据提供者,则必须谨慎行事。