内存分析

本文档指导开发者完成阿里云移动监控iOS SDK的内存分析的功能验证。

1. 大对象

  1. 编写测试代码,触发大块内存分配。例如:

    #import <mach/mach.h>
    
    vm_address_t address;
    vm_size_t size = (vm_size_t)(10 * 1024 * 1024); // 10MB
    kern_return_t ret = vm_allocate((vm_map_t)mach_task_self(), &address, size, VM_FLAGS_ANYWHERE);
    import Darwin
    
    var address: vm_address_t = 0 
    let size: vm_size_t = vm_size_t(10 * 1024 * 1024)   // 10 MB
    let ret: kern_return_t = vm_allocate(mach_task_self_, &address, size, VM_FLAGS_ANYWHERE)
  2. 触发大块内存分配后,大概2分钟后在控制台-内存分析-大对象页面查看

    说明
    • 大对象数据从采集到上传到控制台显示,存在大约2~3分钟延迟;

    image

2. 内存泄漏

  1. 编写测试代码,触发对象之间循环引用。例如:

    @interface CycleTestViewController : UIViewController
    @property (nonatomic, strong) CycleTestViewController *nextVC;
    @end
    
    @implementation CycleTestViewController
    @end
    
    // 创建3CycleTestViewController对象
    CycleTestViewController *vc1 = [[CycleTestViewController alloc] init];
    CycleTestViewController *vc2 = [[CycleTestViewController alloc] init];
    CycleTestViewController *vc3= [[CycleTestViewController alloc] init];
    
    vc1.nextVC = vc2;
    vc2.nextVC = vc3;
    vc3.nextVC = vc1;//形成环:vc3 -> vc1
    import UIKit
    
    class CycleTestViewController: UIViewController {
        var nextVC: CycleTestViewController?
    
        deinit {
            print("\(self) is deallocated")   // 如果发生循环引用,这里永远不会打印
        }
    }
    
    do {
        let vc1 = CycleTestViewController()
        let vc2 = CycleTestViewController()
        let vc3 = CycleTestViewController()
    
        vc1.nextVC = vc2
        vc2.nextVC = vc3
        vc3.nextVC = vc1       // 形成环:vc3 → vc1
    }
  2. 触发循环引用后,应用切换到手机后台,大概2分钟后在控制台-内存分析-内存泄漏页面查看

    image

3. OOM

  1. 编写测试代码,触发应用OOM崩溃。例如:

    #import <Foundation/Foundation.h>
    
    @interface VMAllocator : NSObject
    @property (nonatomic, strong) NSMutableArray *vmAddresses;
    - (void)allocateMemory;
    @end
    
    // VMAllocator.m
    #import "VMAllocator.h"
    #import <mach/mach.h>
    
    @implementation VMAllocator
    
    - (instancetype)init {
        self = [super init];
        if (self) {_vmAddresses = [[NSMutableArray alloc] init];
        }
        return self;
    }
    
    - (void)allocateMemory {
        // 以下会导致应用OOM
        for (NSUInteger i = 0; i < 1000; i++) {
            vm_address_t address;
            vm_size_t size = (vm_size_t)(10 * 1024 * 1024);
            kern_return_t ret = vm_allocate((vm_map_t)mach_task_self(), &address, size, VM_FLAGS_ANYWHERE);
            if (ret != ERR_SUCCESS) {
                NSLog(@"vm_allocate failed");
                return;
            }
            [self.vmAddresses addObject:[NSValue valueWithPointer:(void *)address]];
        }
    }
    
    - (void)dealloc {
        for (NSValue *value in self.vmAddresses) {
            vm_address_t address = (vm_address_t)[value pointerValue];
            vm_deallocate((vm_map_t)mach_task_self(), address,10 * 1024 *1024);
        }
    }
    
    @end
    import Foundation
    import Darwin
    
    class VMAllocator {
        var vmAddresses: [vm_address_t] = []
        
        func allocateMemory() {
            for _ in0..<1000 {
                var address: vm_address_t = 0
                let size: vm_size_t =10 * 1024 * 1024
                let ret = vm_allocate(mach_task_self_, &address, size, VM_FLAGS_ANYWHERE)
                if ret != KERN_SUCCESS {
                    print("vm_allocate failed")
                    return
                }
                vmAddresses.append(address)
            }
        }
        
        deinit {
            for address in vmAddresses {
                vm_deallocate(mach_task_self_, address, 10 * 1024 * 1024)
            }
        }
    }
  2. 应用下次启动后,在控制台-内存分析-OOM页面查看。

    image