Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Huge memory usage despite ARC


I have the following function that opens an image, scales it and saves it to another file.

-(void)writeFileToIcon:(NSString *)fullPath :(NSString *)finalPath :(NSSize)outputSize
{
    NSData *dataToWrite;
    NSBitmapImageRep *rep;

    rep = [NSBitmapImageRep imageRepWithData:[[self scaleImage:[[NSImage alloc]initWithContentsOfFile:fullPath] toSize:outputSize] TIFFRepresentation]];
    dataToWrite = [rep representationUsingType:NSPNGFileType properties:nil];
    [dataToWrite writeToFile:finalPath atomically:YES];
}

- (NSImage *)scaleImage:(NSImage *)image toSize:(NSSize)targetSize
{
    if ([image isValid])
    {
        NSSize imageSize = [image size];
        float width  = imageSize.width;
        float height = imageSize.height;
        float targetWidth  = targetSize.width;
        float targetHeight = targetSize.height;
        float scaleFactor  = 0.0;
        float scaledWidth  = targetWidth;
        float scaledHeight = targetHeight;

        NSPoint thumbnailPoint = NSZeroPoint;

        if (!NSEqualSizes(imageSize, targetSize))
        {
            float widthFactor  = targetWidth / width;
            float heightFactor = targetHeight / height;

            if (widthFactor < heightFactor)
            {
                scaleFactor = widthFactor;
            }
            else
            {
                scaleFactor = heightFactor;
            }

            scaledWidth  = width  * scaleFactor;
            scaledHeight = height * scaleFactor;

            if (widthFactor < heightFactor)
            {
                thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
            }

            else if (widthFactor > heightFactor)
            {
                thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
            }

            NSImage *newImage = [[NSImage alloc] initWithSize:NSMakeSize(scaledWidth, scaledHeight)];

            [newImage lockFocus];

            NSRect thumbnailRect;
            thumbnailRect.origin = NSZeroPoint;
            thumbnailRect.size.width = scaledWidth;
            thumbnailRect.size.height = scaledHeight;

            [image drawInRect:thumbnailRect
                     fromRect:NSZeroRect
                    operation:NSCompositeSourceOver
                     fraction:1.0];

            [newImage unlockFocus];
            return newImage;
        }
        return nil;
    }
    return nil;
}

However each time this function is called, the memory usage is getting higher (up to 5 GB for 1000 calls).
The issue is the drawRect function which seems to take a lot of memory (according to the analyser) but does not release it.
How can I "ask" ARC to release it ?

Thanks.

like image 444
Laurent Crivello Avatar asked Jul 01 '26 18:07

Laurent Crivello


1 Answers

One may need to look at the whole code to find the problem. One idea follows, though: under ARC you cannot call "release" on objects, but if you set the pointer to the object to "nil", the object will be released (unless other strong references to that object exist somewhere).

I suggest you track your code and make sure you don't hold objects you don't need anymore. If your code is well encapsulated and structured, this shouldn't happen.

If your code is well designed, though, there is the chance that this amount of memory is actually needed (unlikely, but don't know without more details). If this would be the case, then let the system manage the memory, it will release the objects when it is appropriate. This, and try to make optimizations somewhere if memory usage is a concern.

Off-topic: these long nested if's with multiple return points within the method are not a very good idea; I suggest you reestructure your code slightly. If you write clearer code, you'll have more control over it, and you will find solutions to problems faster.

like image 153
George Avatar answered Jul 03 '26 10:07

George



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!