Cocoa 创建CGImageRef而不缓存任何内容

Cocoa 创建CGImageRef而不缓存任何内容,cocoa,caching,nsdata,quartz-graphics,core-services,Cocoa,Caching,Nsdata,Quartz Graphics,Core Services,我需要使用CGImageSourceCreateTumbnailAtIndex(…)创建数千个CGImage对象 问题在于,当使用简单的CGDataProviderCreateWithURL(…)后接cgmagesourceCreateTumbnailatindex(…)时,系统会缓存文件的内容(在非活动内存中),这会导致严重的性能损失 最接近的解决方案: ,建议使用[NSData DATA WITH CONTENTS OFURL:inURL options:NSUNCACHEDARD erro

我需要使用CGImageSourceCreateTumbnailAtIndex(…)创建数千个CGImage对象

问题在于,当使用简单的
CGDataProviderCreateWithURL(…)
后接
cgmagesourceCreateTumbnailatindex(…)
时,系统会缓存文件的内容(在非活动内存中),这会导致严重的性能损失

最接近的解决方案:

,建议使用
[NSData DATA WITH CONTENTS OFURL:inURL options:NSUNCACHEDARD error:nil]
然后使用
CGImageSourceCreateWithData(…)
来防止系统缓存文件

最接近解决方案的问题

此解决方案需要在创建缩略图之前将整个文件读取到内存中,这将导致另一个显著的性能损失

我已经尝试过的东西:

  • 使用
    [NSData DATA WITH CONTENTS OFURL:inURL options:NSNCacheDreard | NSData READING MAPPEDAWAYS error:nil]
    但它似乎忽略了
    NSUncachedRead
    选项(文件被缓存到非活动内存中)

  • 使用
    CGDataProviderCreateWithURL
    ,但它也会缓存文件

  • 编辑:使用@justin建议的使用CGDataProvider createsequential(…)创建的自定义
    CGDataProvider
    ,但是
    cgmagesourcecreatewithdataprovider
    调用
    CGDataProviderCopyData
    首先从自定义数据提供程序复制整个图像数据(我只想读取缩略图),甚至在我调用CGImageSourceCreateTumbnailAtIndex之前

  • 有没有关于如何在不将整个文件加载到内存和不缓存的情况下获取缩略图的建议

    另外,在创建图像源和缩略图时,我已经将
    kCGImageSourceShouldCache
    设置为
    kCFBooleanFalse
    ,但它似乎只与解码数据相关,而与读取文件时缓存的原始数据无关


    编辑:我使用10.8。在其他平台/版本上,CGImageSourceCreateWithDataProvider等功能的实现可能有所不同。

    我敦促您确保了解映射内存、虚拟内存和磁盘缓存在目标系统上的实际工作方式(注意:在不同的OS X版本中,实现方式有所不同)。我之所以这么说,是因为大多数Cocoa开发人员不太了解OSX上的磁盘缓存和内存映射,因为它不会妨碍大多数人的工作(是的,这是我自己的假设)。尽管如此,我是花了大量时间与之抗争(甚至归档bug)的极少数人之一;打开和关闭成千上万的媒体资产是其中一种合格的情况,在这种情况下,缓存可能会成为真正的阻碍,或者至少会成为性能障碍


    要绕过缓存,请使用
    CGDataProviderCreateSequential
    创建数据提供程序,并实现自己的读卡器实现,打开文件(例如使用
    fopen
    ),然后在读取之前使用
    fcntl
    F_NOCACHE
    选项禁用缓存。然后,您可以在每次需要数据时运行到磁盘,也可以实施自己的缓存策略,该策略针对您读取的数据进行了优化(例如,在读取文件时将头缓存在内存中,但直接从磁盘读取图像数据)。当您确保文件不能在背后更改时,生活会更轻松。不管怎样,理论上看起来不错。

    谢谢。这是个好主意,我试过了。但是,在实践中,我发现在使用顺序数据源创建CGImageSource(或使用CGImageSourceUpdateDataProvider更新增量图像)时,甚至在创建实际CGImage之前,整个文件都会被读取。@Ben Uri不客气。这种情况下的另一种方法是将整个图像加载到内存中(如上所述,不进行缓存)。如果文件不是很大,那么可以接受,最小化文件io(给定读取每个字节的API约束),并避免磁盘缓存。我在osx上使用磁盘缓存时遇到的一个问题是,它会消耗所有可用内存,并且在内存耗尽时不会足够快地退出页面,从而导致疯狂的抖动和分页。因此,如果您正在读取大量图像,以这种方式读取整个文件可能是“最好的”。但是,实际上使用映射内存可能要好得多,因为API不幸读取了整个文件。