I’m engaged on a undertaking the place the UI has to generate previews for a lot of bigger nonetheless photos. I’m utilizing a C++ library to use varied lookup tables and conversions to the photographs which requires the picture to be in a RGB float buffer. I take advantage of Speed up to transform the supply picture into Float and again right into a RGB picture. I’m managing conversion jobs by means of a serial DispatchQueue in order that one conversion is finished after one other.
What I’m working into is peak reminiscence points. Even supposing I handle jobs sequentially and processing photos one after the other I pile up reminiscence within the GB vary. If I’ve sufficient reminiscence to finish all processing the reminiscence will get freed and nothing leaks – however throughout processing I’m utilizing up a number of occasions extra reminiscence than I ought to.
In devices I’ve checked that I stack up vImage_Buffer situations (each operation creates 3 however I see many) every a number of MB in measurement – regardless of calling free() on the buffers within the operate on the finish.
I’m quite clueless atm about why it piles up reminiscence? My working concept is that vImage_Buffer.free() doesn’t free reminiscence immidiately? However wants one thing to occur to really free the reminiscence (it looks as if it frees it when all of the processing is finished, however these are impartial jobs actually and there’s no widespread factor that claims I am carried out.). I’m really fairly puzzled. How can I restrict the quantity of reminiscence I eat? I’ve considered retaining the buffers round – however the issue is that the photographs would not have the identical measurement.
It’s the first time I take advantage of Speed up and vImage – what did I miss?
Any perception could be a lot appreciated….
Right here is the operate (sure I do name free()):
@out there(iOS 16.0,*)
static func processImage(from cgImage:CGImage, lookData:Knowledge) throws -> CGImage {
let width = UInt32(cgImage.width)
let peak = UInt32(cgImage.peak)
let Rec709 = CGColorSpace(title: CGColorSpace.itur_709)!
let bitmapInfo_3ChanFloat:CGBitmapInfo = CGBitmapInfo(
rawValue:CGBitmapInfo.floatComponents.rawValue | CGBitmapInfo.byteOrder32Little.rawValue | CGImageAlphaInfo.none.rawValue
)
var src_format = vImage_CGImageFormat(
bitsPerComponent: cgImage.bitsPerComponent,
bitsPerPixel: cgImage.bitsPerPixel,
colorSpace: cgImage.colorSpace!,
bitmapInfo: cgImage.bitmapInfo)!
var convertible_format = vImage_CGImageFormat(
bitsPerComponent: 32,
bitsPerPixel: 3 * 32,
colorSpace: cgImage.colorSpace!,
bitmapInfo: bitmapInfo_3ChanFloat)!
var converted_format = vImage_CGImageFormat(
bitsPerComponent: 32,
bitsPerPixel: 3 * 32,
colorSpace: Rec709,
bitmapInfo: bitmapInfo_3ChanFloat)!
var end_format = vImage_CGImageFormat(
bitsPerComponent: 8,
bitsPerPixel: 4 * 8,
colorSpace: Rec709,
bitmapInfo: .init(rawValue: CGImageAlphaInfo.noneSkipLast.rawValue))!
let to_converter = vImageConverter_CreateWithCGImageFormat(
&src_format,
&convertible_format,
nil,
vImage_Flags(kvImagePrintDiagnosticsToConsole),
nil).takeRetainedValue()
let back_converter = vImageConverter_CreateWithCGImageFormat(
&converted_format,
&end_format,
nil,
vImage_Flags(kvImagePrintDiagnosticsToConsole),
nil).takeRetainedValue()
var src_buffer = attempt vImage_Buffer(cgImage: cgImage)
var conversion_buffer = vImage_Buffer()
vImageBuffer_Init(
&conversion_buffer,
UInt(peak),
UInt(width),
convertible_format.bitsPerPixel,
vImage_Flags(kvImagePrintDiagnosticsToConsole)
)
var end_buffer = vImage_Buffer()
vImageBuffer_Init(
&end_buffer,
UInt(peak),
UInt(width),
end_format.bitsPerPixel,
vImage_Flags(kvImagePrintDiagnosticsToConsole)
)
vImageConvert_AnyToAny(
to_converter,
&src_buffer,
&conversion_buffer,
nil,
vImage_Flags(kvImagePrintDiagnosticsToConsole)
)
let imageBuffer = conversion_buffer.information.assumingMemoryBound(to: Float.self)
let measurement = Int(width * peak * 4 * 3)
attempt lookData.withUnsafeBytes { (rawLookBuffer:UnsafeRawBufferPointer) in
let lookBuffer:UnsafePointer<UInt8> = rawLookBuffer.baseAddress!.assumingMemoryBound(to: UInt8.self)
let end result = applyLook_CPP(imageBuffer, measurement, width, peak, lookBuffer, rawLookBuffer.depend)
if end result < 0 {
throw Errors.ImageSDKFailed(error: end result)
}
}
vImageConvert_AnyToAny(
back_converter,
&conversion_buffer,
&end_buffer,
nil,
vImage_Flags(kvImagePrintDiagnosticsToConsole)
)
let end result = attempt end_buffer.createCGImage(format: end_format)
src_buffer.free()
conversion_buffer.free()
end_buffer.free()
return end result
}