5

我正在与CGContextDrawImage/CGDataProviderCopyData函数中的内部缓存(15 mp 图像大约 90 MB)作斗争。
这是分析器中的堆栈跟踪:

在此处输入图像描述

在所有情况下,IOSurface都被创建为“缓存”,并且在@autoreleasepool耗尽后不会被清除。
这使得应用程序生存的机会非常少。
缓存不依赖于图像大小:我尝试渲染,512x512以及(全尺寸) 图像块。4500x5124500x2500

在清理它们之前 ,我使用@autoreleasepool,CFGetRetainCount返回1所有对象。CG

操作数据的代码:

+ (void)render11:(CIImage*)ciImage fromRect:(CGRect)roi toBitmap:(unsigned char*)bitmap {
    @autoreleasepool
    {
        int w = CGRectGetWidth(roi), h = CGRectGetHeight(roi);

        CIContext* ciContext = [CIContext contextWithOptions:nil];
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

        CGContextRef cgContext = CGBitmapContextCreate(bitmap, w, h,
                                                   8, w*4, colorSpace,
                                                   kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);


        CGImageRef cgImage = [ciContext createCGImage:ciImage
                                         fromRect:roi
                                           format:kCIFormatRGBA8
                                       colorSpace:colorSpace
                                         deferred:YES];


        CGContextDrawImage(cgContext, CGRectMake(0, 0, w, h), cgImage);

        assert( CFGetRetainCount(cgImage) == 1 );

        CGColorSpaceRelease(colorSpace);
        CGContextRelease(cgContext);
        CGImageRelease(cgImage);
    }
}


我所知道的IOSurface:它来自以前的私有框架IOSurface
CIContext有一个功能render: ... toIOSurface:
我已经创建了 myIOSurfaceRef并将其传递给了这个函数,内部实现仍然创建了自己的表面,并且不清理它。

那么,您是否知道(或假设): 1. 除了/
之外,还有其他方法可以读取 CGImage 的数据缓冲区 吗? 2. 有没有办法在渲染时禁用缓存? 3. 为什么会发生缓存? 4. 我可以使用一些较低级别的(非私有的)API 来手动清理系统内存吗?CGContextDrawImageCGDataProviderCopyData



欢迎任何建议。

4

2 回答 2

5

要回答你的第二个问题,

Is there a way to disable caching at render?

将环境变量设置CI_SURFACE_CACHE_CAPACITY为 0 将或多或少地禁用CIContext表面缓存。此外,您可以通过将该变量设置为以字节为单位的给定值来指定自定义(近似)缓存限制。例如,设置CI_SURFACE_CACHE_CAPACITY为 2147483648 指定 2 GiB 表面缓存限制。

请注意,一个进程的所有实例似乎都CIContext共享一个表面缓存。每个CIContext.

于 2018-12-10T03:11:45.083 回答
1

如果只需要操作 CIImage 数据,可以考虑使用 CIImageProcessorKernel 将数据放入 CPU 或 GPU 计算而不提取它们。

我注意到

[ciContext render:image toBitmap:bitmap rowBytes: w*4 bounds:image.extent format:kCIFormatRGBA8 colorSpace:colorSpace];

没有这样的90M缓存。也许这就是你想要的。

在此处输入图像描述

于 2018-11-09T20:47:34.850 回答