美文网首页
iOS内存管理策略”Tagged-Pointer“没你想的那么简

iOS内存管理策略”Tagged-Pointer“没你想的那么简

作者: 一眼万年的星空 | 来源:发表于2022-07-30 17:24 被阅读0次

    本文主要研究Tagged Pointer技术,针对该技术需要解决的问题、以及在实际应用中的价值做一些简单的探讨。

    如果你想要更进一步,去挖掘Tagged Pointer是如何实现的,可以参考Friday Q&A 2012-07-27: Let's Build Tagged Pointersobjc源码

    另外,本文中涉及到的示例代码,请在真机iOS设备上测试,因为Tagged Pointer技术针对不同的平台,具体实现细节是有差异的,否则无法得出和本文一致的测试结果。

    一、对象的内存

    下面我们针对iOS中对象进行一些探究,代码如下,其完整代码见TaggedPointer

    
        __weak NSNumber *weakNumber;
        __weak NSString *weakString;
        __weak NSDate *weakDate;
        __weak NSObject *weakObj;
        int num = 123;
        
        @autoreleasepool {
            weakObj = [[NSObject alloc] init];
            weakNumber = [NSNumber numberWithInt:num];
            weakString = [NSString stringWithFormat:@"string%d", num];
            weakDate   = [NSDate dateWithTimeIntervalSince1970:0];
        }
        NSLog(@"weakObj is %@", weakObj);
        NSLog(@"weakNumber is %@", weakNumber);
        NSLog(@"weakString is %@", weakString);
        NSLog(@"weakDate is %@", weakDate);
    

    第7行,首先定义了4个__weak***对象,构建了一个autoreleasepool,所以在12行之后,所有__weak修饰的弱引用对象,都会被释放。经过上面分析,我们得出,对象会打印出null

    但是,实际上,我们得到了如下的输出。

    TaggedPointer[3570:3928309] weakObj is (null)

    TaggedPointer[3570:3928309] weakNumber is 123

    TaggedPointer[3570:3928309] weakString is string123

    TaggedPointer[3570:3928309] weakDate is Thu Jan 1 08:00:00 1970

    可以看到,只有NSObject对应的对象值是null,其他的值,均正常打印。

    这是因为NSNumberNSStringNSDate,在这里采用了Tagged Pointer技术。

    二、Tagged Pointer

    2.1 Tagged Pointer技术

    2.1.1 简介

    1

    2.2.2 未引入Tagged Pointer

    1

    2.2.3 引入Tagged Pointer

    1

    2.2.4 判断是否是Tagged Pointer

    1

    2.2 应用

    2.2.1 支持的对象类型

    可以从objc源码中找出支持Tagged Pointer 的对象类型,如下:

    
    typedef uint16_t objc_tag_index_t;
    enum
    {
        OBJC_TAG_NSString          = 2, 
        OBJC_TAG_NSNumber          = 3, 
        OBJC_TAG_NSIndexPath       = 4, 
        OBJC_TAG_NSDate            = 6, 
        ....
    };
    

    即针对NSStringNSNumberNSDateNSIndexPath这些类型,都支持Tagged Pointer技术。

    2.2.2 NSNumber

    我们通过NSNumber以及NSString对象来观察Tag+Data的存储形式。

    示例代码参见:TaggedPointer

    如下所示,我们创建了很多NSNumber对象:

        NSNumber *number1 = @1;                          //0xb000000000000012
        NSNumber *number2 = @2;                          //0xb000000000000022
        NSNumber *number3 = @(0xFFFFFFFFFFFFFFF);        //0x1c0022560
        NSNumber *number4 = @(1.2);                      //0x1c0024b80
        int num4 = 5;
        NSNumber *number5 = @(num4);                     //0xb000000000000052
        long num5 = 6;
        NSNumber *number6 = @(num5);                     //0xb000000000000063
        float num6 = 7;
        NSNumber *number7 = @(num6);                     //0xb000000000000074
        double num7 = 8;
        NSNumber *number8 = @(num7);                     //0xb000000000000085
        
        //值:0xb000000000000012 0xb000000000000022 0x1c0022560 0x1c0024b80 0xb000000000000052 0xb000000000000063 0xb000000000000074 0xb000000000000085
        NSLog(@"%p %p %p %p %p %p %p %p", number1, number2, number3, number4, number5, number6, number7, number8);
    

    由上表我们得出:

    • 很大的数字,超过Tagged Pointer表示上限的时候,将会转为对象存储,存放在堆上;
    • 如果是含有小数点的浮点数,将会直接以对象方式存储;
    • 其余类型的数字,包括不含小数部分的浮点型和整型都会以Tagged Pointer存储。

    并且,针对以上部分,我们整理出Tagged Pointer的存储格式如下,以number1为例:

    1

    2.2.3 NSString

    同上面NSNumber的处理逻辑,NSString处理的类似。

    
    NSString *str1 = @"a";                                          //0x1049cc248
    NSString *str2 = [NSString stringWithFormat:@"a"];              //0xa000000000000611
    NSString *str3 = [NSString stringWithFormat:@"bccd"];           //0xa000000646363624
    NSString *str4 = [NSString stringWithFormat:@"c"];              //0xa000000000000631
    NSString *str5 = [NSString stringWithFormat:@"cdasjkfsdljfiwejdsjdlajfl"];//0x1c02418f0
    NSLog(@"%@ %@ %@ %@ %@",
          [str1 class],   //__NSCFConstantString
          [str2 class],   //NSTaggedPointerString
          [str3 class],   //NSTaggedPointerString
          [str4 class],   //NSTaggedPointerString
          [str5 class]);  // __NSCFString
    

    根据以上结果,我们将NSString分类三类:

    • 常量类型:__NSCFConstantString,定义的字符串常量。
    • Tagged Pointer类型:NSTaggedPointerString,通过对象方法创建的短字符串。
    • NSString对象类型:__NSCFString,包括NSString、NSMutableString等创建的字符串对象。

    以上,整理如下:

    1

    NSString以Tagged Pointer的存储格式如下:

    1

    2.3 内存管理

    1

    三、一个面试问题的研究

    该面试题如下:

    1

    参考

    链接

    1Friday Q&A 2012-07-27: Let's Build Tagged Pointers
    2Tagged Pointer wiki
    3NSString retain count -1
    4objc源码

    示例代码

    1TaggedPointer

    相关文章

      网友评论

          本文标题:iOS内存管理策略”Tagged-Pointer“没你想的那么简

          本文链接:https://www.haomeiwen.com/subject/nwqhwrtx.html