I have a memory leak (App memory is just increasing) when using a CoreML prediction. I can't find any documentation or examples where something is being released that I might be missing. In my real project I've got ARC disabled, but not here (so the compiler won't allow me to manually release anything, so I guess those things I've tried don't need it)
I've reduced it down to a minimal case available on github. But here is 99% of it (the repository just has the model and additional project assets, and more error checking - no errors, the prediction runs fine, but cut down for stackoverflow)
#import <Cocoa/Cocoa.h>
#import "SsdMobilenet.h"
#include <string>
#include <iostream>
uint8_t ImageBytes[300*300*4];
CVPixelBufferRef MakePixelBuffer(size_t Width,size_t Height)
{
auto* Pixels = ImageBytes;
auto BytesPerRow = Width * 4;
CVPixelBufferRef PixelBuffer = nullptr;
auto Result = CVPixelBufferCreateWithBytes( nullptr, Width, Height, kCVPixelFormatType_32BGRA, Pixels, BytesPerRow, nullptr, nullptr, nullptr, &PixelBuffer );
return PixelBuffer;
}
int main(int argc, const char * argv[])
{
auto* Pixels = MakePixelBuffer(300,300);
SsdMobilenet* ssd = nullptr;
for ( auto i=0; i<10000; i++ )
{
if ( !ssd )
{
ssd = [[SsdMobilenet alloc] init];
}
auto* Output = [ssd predictionFromPreprocessor__sub__0:Pixels error:nullptr];
}
return 0;
}
Is there something I'm supposed to clear, free, release, dealloc? I've tried releasing the ssd and recreating it every iteration, but that doesn't help.
On HighSierra 10.13.6, xcode 10.1 (10B61).
Leak occurring on this 2011 imac (no metal, CPU execution) and a 2013 Retina MBP (which runs on GPU), and with other models, not just SSDMobileNet.
Edit 1: Looking into instruments, using Generations/Snapshots, it really seems like it's the output leaking, but I cannot dealloc
or release
it, so maybe there's something else I need to do to free the results?
The <non-object>
's are all allocations inside apply_convulution_layer()
calls deep inside CoreML.
Thanks to @Matthijs-Hollemans, using an NSAutoReleasePool
with ARC disabled, this doesn't leak. (I can also auto-release the SSD, but this particular combination keeps the pre-allocated SSD persistent).
I don't have a solution for ARC/AutoReferenceCounting builds, as NSAutoReleasePool
is unavailable.
int main(int argc, const char * argv[])
{
auto* Pixels = MakePixelBuffer(300,300);
SsdMobilenet* ssd = [[SsdMobilenet alloc] init];
//SsdMobilenet* ssd = nullptr;
for ( auto i=0; i<10000; i++ )
{
NSAutoreleasePool* pool= [[NSAutoreleasePool alloc]init];
if ( !ssd )
{
ssd = [[SsdMobilenet alloc] init];
}
auto* Output = [ssd predictionFromPreprocessor__sub__0:Pixels error:nullptr];
//[Output release];
//[ssd release];
//ssd = nullptr;
[pool drain];
}
return 0;
}