10

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?

pmoosman
  • 101
  • 1
  • 3

2 Answers2

5

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];
}
jjxtra
  • 20,415
  • 16
  • 100
  • 140
3

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.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • 1
    However, Apple may tell you that no one in his right mind would use 500 labels. After all, this is why tables reuse their cells; you can have a 1000 row table but it only contains about 12 actual cells (so, only about 12 actual labels if there is one label per row). – matt May 13 '14 at 02:20
  • i don't think this answer is accurate. i can't imagine views are backed by bitmaps. maybe labels are, but i'm would be surprised if every view would be. you have any link for this? – kritzikratzi May 19 '15 at 22:38
  • @kritzikratzi I didn't say views are backed by bitmaps. I said that my _first response_ was to say that they are. My understanding of how this works comes from various WWDC videos where Apple does, in fact, talk about the bitmap backing a view. – matt May 19 '15 at 22:45
  • i think its only backed by a bitmap if you rasterize the layer, or if you use a uilabel. not for other views. my guess is it's not a bug, but a performance issue (it's quite expensive to render text, so always rasterizing labels would make sense) – kritzikratzi May 20 '15 at 11:19
  • @kritzikratzi on iOS 7+ UILabel is always backed by a texture, regardless of rasterization setting. You can prove this by allocating a UILabel and then scaling it really big or changing the bounds really big and watching the memory usage go up or app crash. – jjxtra May 20 '15 at 15:30
  • yes. that's what i said. uilabels are backed by textures, uiviews are not- unless you rasterize. – kritzikratzi May 20 '15 at 15:32