Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UILabel (CALayer) is using large amounts of virtual memory

In Xcode and Instruments I see UILabel (CALayer) using large amounts of virtual memory (Anonymous VM). I see about 235 KB of virtual memory per UILabel.

I think this perhaps is a new issue with iOS 7.1 or 7.1.1.

Is this expected?

I created a simple program that creates 500 UILabels and Instruments shows 115MB of memory used. At about 1500 labels the application is terminated by the OS.

for (int i = 0; i < 500; i++)
{
    index = (int)[self.items count];
    index++;

    frame = CGRectMake(10.0, 20, 300.0, 50.0);

    UILabel *newLabel = [[UILabel alloc] initWithFrame:frame];
    newLabel.text = [NSString stringWithFormat:@"This is text for label: %d", index];
    newLabel.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:newLabel];

    [self.items setObject:newLabel forKey:[NSNumber numberWithInteger:index]];
}

Thoughts?

like image 928
pmoosman Avatar asked May 13 '14 01:05

pmoosman


2 Answers

UILabel, and any view that uses drawRect (at least on iOS 7+) is backed by a texture, so every UILabel will use a lot of memory, the larger the label, the more memory used.

I've found this especially painful in my photo editing extension for You Doodle which allows adding text in the Photos app. Unfortunately I have to greatly restrict the scale range of the text because photo extensions are much more limited to memory usage than regular apps before they crash.

This can easily be verified by running instruments and allocating a bunch of large UILabel's and setting their text and ensuring they are all visible, i.e.:

CGRect f = CGRectMake(0.0.0f, 0.0f, 300.0f, 300.0f);
for (NSInteger i = 0; i < 100; i++)
{
    UILabel* l = [[UILabel alloc] initWithFrame:f];
    l.backgroundColor = UIColor.blueColor;
    l.textColor = UIColor.whiteColor;
    l.text = @"UILabel text for the memory test";
    l.numberOfLines = 0;
    [self.view addSubview:l];
}
like image 76
jjxtra Avatar answered Nov 16 '22 03:11

jjxtra


When reporting this kind of thing (to Stack Overflow or to Apple), you really should eliminate unnecessary excess code. This code is sufficient to reproduce the phenomenon:

for (int i = 0; i < 500; i++)
{
    CGRect frame = CGRectMake(10.0, 20, 300.0, 50.0);
    UILabel *newLabel = [[UILabel alloc] initWithFrame:frame];
    newLabel.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:newLabel];
}

That causes the app to use 129MB on my machine. (No need to use Instruments: Xcode now shows memory usage directly.)

My first response was: "I guess I don't find this terribly surprising. If you change the frame to a smaller rect, less memory is used. Views are expensive! They are backed by a bitmap."

However, if you change the UILabel to a plain UIView, only 13MB is used. I think that's a sufficient difference to warrant filing a bug.

like image 3
matt Avatar answered Nov 16 '22 04:11

matt