关于@autoreleasepool的性能测试及手动释放自动释放池

2024-01-24 16:38

本文主要是介绍关于@autoreleasepool的性能测试及手动释放自动释放池,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文地址:http://yangchao0033.github.io/blog/2015/12/31/guan-yu-at-autoreleasepoolde-ce-shi-ji-shi-yong/

首先,我们先对使用autoreleasepool的场景进行性能对比。

  • 不用autoreleasepool
- (void)doSomething {NSMutableArray *collection = @[].mutableCopy;for (int i = 0; i < 10e6; ++i) {NSString *str = [NSString stringWithFormat:@"hi + %d", i];[collection addObject:str];}NSLog(@"finished!");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8


不使用性能如下如所示: 
不使用

  • 使用autoreleasepool
- (void)doSomething {NSMutableArray *collection = @[].mutableCopy;for (int i = 0; i < 10e6; ++i) {@autoreleasepool {NSString *str = [NSString stringWithFormat:@"hi + %d", i];[collection addObject:str];}}NSLog(@"finished!");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

使用效果如下图所示: 
使用autoreleasepool

综上,当需要在程序中创建大量的临时变量时(大量也可指数量多,不确定,比如从数据库中读取数据时),很容易使内存产生峰值又回到内存低谷,这样对程序的性能会产生很大影响,而使用自动释放池后,峰值明显有所下降。 
原因:由于在mian函数中已经为我们添加了自动释放池,如下所示: 

#import <UIKit/UIKit.h>
#import "AppDelegate.h"int main(int argc, char * argv[]) {@autoreleasepool {return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

而当autoreleasepool的右括号结束后,会对整个autoreleasepool做一次倾倒。但是这会使其中局部产生的大量零时变量无法及时释放,直到for循环结束后抵达main中autoreleasepool的右括号位置才能释放。这样会在局部位置发生内存峰值。 
官方提出的解决方案是,在大量产生局部变量的位置用autoreleasepool代码块进行包装。比如for循环中要执行的语句,这样每次for循环结束后就会及时收回临时变量占用的内存空间。 

思考:如何在指定的次数时,及时释放自动释放池中的临时变量

使用mrc下的特性
在编译选项中,为MRC的程序添加-fno-objc-arc标记,表明在编译时,该文件使用MRC编译
如果要在MRC项目中添加ARC的文件,可以使用 -fobjc-arc 标记即可
  • 1
  • 2
  • 3

这里的需求我们可以使用MRC时代的一个重量级的自动释放池,通常用来创建偶尔需要释放清空的池。

- (void)doSomething {int count = 0;NSMutableArray *collection = @[].mutableCopy;NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];for (int i = 0; i < 10e6; ++i) {NSString *str = [NSString stringWithFormat:@"hi + %d", i];[collection addObject:str];if (++count == 100) {/** 每一百次倾倒一次池子 */[pool drain];count = 0;}}/** 用来倾倒当i的个数不是100的倍数时,比如读取数据库数据时,数据总数为不确定值 */[pool drain];NSLog(@"finished!");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

这篇关于关于@autoreleasepool的性能测试及手动释放自动释放池的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/640310

相关文章

C++,C#,Rust,Go,Java,Python,JavaScript的性能对比全面讲解

《C++,C#,Rust,Go,Java,Python,JavaScript的性能对比全面讲解》:本文主要介绍C++,C#,Rust,Go,Java,Python,JavaScript性能对比全面... 目录编程语言性能对比、核心优势与最佳使用场景性能对比表格C++C#RustGoJavapythonjav

CPython与PyPy解释器架构的性能测试结果对比

《CPython与PyPy解释器架构的性能测试结果对比》Python解释器的选择对应用程序性能有着决定性影响,CPython以其稳定性和丰富的生态系统著称;而PyPy作为基于JIT(即时编译)技术的替... 目录引言python解释器架构概述CPython架构解析PyPy架构解析架构对比可视化性能基准测试测

Apache服务器IP自动跳转域名的问题及解决方案

《Apache服务器IP自动跳转域名的问题及解决方案》本教程将详细介绍如何通过Apache虚拟主机配置实现这一功能,并解决常见问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,... 目录​​问题背景​​解决方案​​方法 1:修改 httpd-vhosts.conf(推荐)​​步骤

idea-java序列化serialversionUID自动生成方式

《idea-java序列化serialversionUID自动生成方式》Java的Serializable接口用于实现对象的序列化和反序列化,通过将对象转换为字节流来存储或传输,实现Serializa... 目录简介实现序列化serialVersionUID配置使用总结简介Java.io.Seripyth

Java JAR 启动内存参数配置指南(从基础设置到性能优化)

《JavaJAR启动内存参数配置指南(从基础设置到性能优化)》在启动Java可执行JAR文件时,合理配置JVM内存参数是保障应用稳定性和性能的关键,本文将系统讲解如何通过命令行参数、环境变量等方式... 目录一、核心内存参数详解1.1 堆内存配置1.2 元空间配置(MetASPace)1.3 线程栈配置1.

Linux云服务器手动配置DNS的方法步骤

《Linux云服务器手动配置DNS的方法步骤》在Linux云服务器上手动配置DNS(域名系统)是确保服务器能够正常解析域名的重要步骤,以下是详细的配置方法,包括系统文件的修改和常见问题的解决方案,需要... 目录1. 为什么需要手动配置 DNS?2. 手动配置 DNS 的方法方法 1:修改 /etc/res

JAVA实现Token自动续期机制的示例代码

《JAVA实现Token自动续期机制的示例代码》本文主要介绍了JAVA实现Token自动续期机制的示例代码,通过动态调整会话生命周期平衡安全性与用户体验,解决固定有效期Token带来的风险与不便,感兴... 目录1. 固定有效期Token的内在局限性2. 自动续期机制:兼顾安全与体验的解决方案3. 总结PS

linux部署NFS和autofs自动挂载实现过程

《linux部署NFS和autofs自动挂载实现过程》文章介绍了NFS(网络文件系统)和Autofs的原理与配置,NFS通过RPC实现跨系统文件共享,需配置/etc/exports和nfs.conf,... 目录(一)NFS1. 什么是NFS2.NFS守护进程3.RPC服务4. 原理5. 部署5.1安装NF

Docker多阶段镜像构建与缓存利用性能优化实践指南

《Docker多阶段镜像构建与缓存利用性能优化实践指南》这篇文章将从原理层面深入解析Docker多阶段构建与缓存机制,结合实际项目示例,说明如何有效利用构建缓存,组织镜像层次,最大化提升构建速度并减少... 目录一、技术背景与应用场景二、核心原理深入分析三、关键 dockerfile 解读3.1 Docke

MyBatis Plus实现时间字段自动填充的完整方案

《MyBatisPlus实现时间字段自动填充的完整方案》在日常开发中,我们经常需要记录数据的创建时间和更新时间,传统的做法是在每次插入或更新操作时手动设置这些时间字段,这种方式不仅繁琐,还容易遗漏,... 目录前言解决目标技术栈实现步骤1. 实体类注解配置2. 创建元数据处理器3. 服务层代码优化填充机制详