标签:ios 系统 内存 instrument 性能
在iOS内,指针的地址范围很大, 32位CPU上有 4GB 大小, 64位CPU上有 18EB 大小 (大约有2的60次方), 这么大的指针地址范围会致使我们看来系统内存有这么大,实际上物理内存可能没有这么大,这个大小被称为虚拟内存, 在OS X 中系统使用硬盘来存储内存中不经常使用的数据来作为内存的后备存储, 在内存中存有硬盘数据的指针地址, 需要的事后才写入内存.
然而, 在iOS中没有后备存储, iOS中只读类型的数据已经存在硬盘上, 在需要时写入内存使用, 可读写数据是常驻内存的,不会移除, 一旦可使用内存达到临界值, 系统会发出内存不够用的警告,由应用程序主动释放资源,若释放失败或没有排除警告,会直接被系统终结程序.
虚拟内存
iOS的物理内存被分割成大小为 4KB 的页, 而且不是所有的页都能被应用访问到. 虚拟内存是在kernel和应用层之间的一层,由于当我们每次需要内存的时候都直接调用kernel去申请内存的过程的代价是很大的, 所以底层会直接与虚拟内存申请空间, 虚拟内存会与kernel通信, 创建 VM Object来匹配物理内存,如图:
在内存的堆中, 我们应用的数据只占一部分, 其他还有framework创建的对象和缓存, 内存中还有一些静态常量, 线程的堆栈, 图片数据, CALayer的缓存, 数据库的缓存
干净内存: 从磁盘上拷贝到内存中的空间, 比如, 代码, framework,内存映射文件.
脏内存: 其他的内存空间. 比如 在堆上的初始化数据, 数据库缓存,解压的图片数据等.
大部分应用初始化的数据都是脏内存
举例如下:
- (void)displayWelcomeMessage {
NSString *welcomeMessage = [NSString stringWithUTF8String:“Welcome to WWDC!”];
self.alertView.title = welcomeMessage;
[self.alertView show];
}
welcomeMessage 是脏内存, 因为字符串Welcome to WWDC!
在静态数据区,它倍复制一份到堆上给了welcomeMessage.
- (void)displayWelcomeMessage {
NSString *welcomeMessage = @”Welcome to WWDC!”;
self.alertView.title = welcomeMessage;
[self.alertView show];
}
这次welcomeMessage是干净内存, 因为没有复制一份.
- (void)allocateSomeMemory {
void *buf = malloc(10 * 1024 * 1024);
…
}
虽然malloc是在堆上初始化数据, 但是 buf 没有实际存储数据, 所有buf是干净内存.
- (void)allocateSomeMemory {
void *buf = malloc(10 * 1024 * 1024);
for (unsigned int i = 0; i < sizeof(buf), i++) {
buf[i] = (char)random();
}
…
}
但是一旦使用了buf后, buf就是脏内存了.
UIImage *wwdcLogo = [UIImage imageNamed:@”WWDC12Logo”];
初始化UIImage,UIImage其实是CGImage的包装, CGImage生成jpeg 和 bitmap, 在内存中会有未压缩的bitmap数据,是脏内存.
iOS开始的时候, 干净内存比例很大,当我们运行app的时候, 随着运行的进行, 初始化数据, 产生了脏内存, 进而是脏内存比例增大,干净内存比例减小, 最后产生内存压力, 内存不够用了, 这时候系统会终结掉后台应用, 释放属于应用的脏数据, 腾出内存空间.
-[id <UIApplicationDelegate> -applicationDidReceiveMemoryWarning:]
-[UIViewController didReceiveMemoryWarning]
一定要注意脏内存,因为脏内存是由应用创建,如果不清除,只有应用被终结后才能释放, 使用Profile的VM Tracker去检测内存使用情况, 避免出现大范围经常性波动, 减少内存还可以使用 @autoreleasepool
.
如何检测内存问题
内存不应该在重复一个操作中持续增长, 比如: push和pop UIViewcontroller,滑动UITableview, 操作数据库搜索
使用 Allocations Instrument 来检测内存是否泄露, 遇到内存泄露可以检查是否在块中使用了self对象, 应该换成 __weak 修饰的self这样不增加计数引用.
更多的信息可以查阅官方手册.
Instruments Documentation
Instruments User Guide
Instruments User Reference
地址
如有不正确,欢迎批评!
标签:ios 系统 内存 instrument 性能
原文地址:http://blog.csdn.net/mysevenmi/article/details/45306951