HarmonyOS Next开发学习手册——内存管理(GC)

news2024/9/20 7:49:51

GC(全称 Garbage Collection),即垃圾回收。在计算机领域,GC就是找到内存中的垃圾,释放和回收内存空间。当前主流编程语言实现的GC算法主要分为两大类:引用计数和对象追踪(即Tracing GC)。ArkTS运行时中就是基于分代模型和混合算法来实现不同场景下内存回收的高性能表现。

在ArkTS中,数据类型分为两类,简单类型和引用类型。简单类型内容直接保存在栈(Stack)中,由操作系统自动分配和释放。引用类型保存在堆(heap)中,需要引擎进行手动释放。GC就是针对堆空间的内存自动回收的管理机制。

Heap结构及其配置参数

Heap结构

  • SemiSpace:年轻代(Young Generation),存放新创建出来的对象,存活率低,主要使用copying算法进行内存回收。
  • OldSpace:老年代(Old Generation),存放年轻代多次回收仍存活的对象会被复制到该空间,根据场景混合多种算法进行内存回收。
  • HugeObjectSpace:大对象空间,使用单独的region存放一个大对象的空间。
  • ReadOnlySpace:只读空间,存放运行期间的只读数据。
  • NonMovableSpace:不可移动空间,存放不可移动的对象。
  • SnapshotSpace:快照空间,转储堆快照时使用的空间。
  • MachineCodeSpace:机器码空间,存放程序机器码。

注:每个空间会有一个或多个region进行分区域管理,region是空间向内存分配器申请的单位。

相关参数

注意
以下参数未提示可配置的均为不可配置项,由系统自行设定。

以下参数值有多个阶段划分的对应heap总大小64MB-128MB/128MB-256MB/大于256MB三个阶段的范围情况,剩余内存空间充足的情况下默认均为第三段大于256MB情况。

Semi Space

heap中会生成两个Semi Space供copying使用。

参数名称范围作用
semiSpaceSize2MB-4MB/2MB-8MB/2MB-16MBsemispace空间大小,会根据堆总大小有不同的范围限制
semiSpaceTriggerConcurrentMark1M/1.5M/1.5M首次单独触发Semi Space的并发mark的界限值,超过该值则触发
semiSpaceStepOvershootSize2MB允许过冲最大大小

其他空间

参数名称范围作用
defaultReadOnlySpaceSize256 KBReadOnlySpace默认空间大小
defaultNonMovableSpaceSize2 MB/6 MB/64 MBNonMovableSpace默认空间大小
defaultSnapshotSpaceSize512 KB/512 KB/ 4 MBSnapshotSpace默认空间大小
defaultMachineCodeSpaceSize2 MB/2 MB/8 MBMachineCodeSpace默认空间大小

Old Space 和 Huge Object Space

初始化时都设定为Heap剩余未分配空间的大小。

参数名称范围作用
oldSpaceOvershootSize4MB/8MB/8MBoldSpace允许过冲最大大小

堆大小相关参数

参数名称范围作用
HeapSize448MB-1024MB堆总大小,实际系统分配大小根据堆类型不同分配不同,或内存池不够会降低下限
SemispaceSize2MB-4MB/2MB-8MB/2MB-16MBsemispace空间大小
NonmovableSpaceSize2MB/6MB/64MBnonmovableSpace空间大小
SnapshotSpaceSize512KB快照空间大小,
MachineCodeSpaceSize2MB机器码空间大小

worker线程堆上限

参数名称范围作用
heapSize768 MBwork类型heap空间大小

解释器栈大小

参数名称范围作用
maxStackSize128KB控制解释器栈帧大小

并发参数

参数名称作用
gcThreadNum7gc线程数量,默认为7,可通过gc-thread-num参数自行设定该参数值
MIN_TASKPOOL_THREAD_NUM3线程池最小线程数
MAX_TASKPOOL_THREAD_NUM7线程池最大线程数

注:该线程池主要用于执行GC流程中的并发任务,实际线程池初始化综合参考gcThreadNum以及线程上下限,gcThreadNum为负值时初始化线程池线程数 = cpu核心数/2

其他参数

参数名称作用
minAllocLimitGrowingStep2M/4M/8Mheap整体重新计算空间大小限制时,控制oldSpace、heapObject和globalNative的最小增长步长
minGrowingStep4M/8M/16M调整oldSpace的最小增长步长
longPauseTime40ms判断是否为超长GC界限,超长GC会触发完整GC日志信息打印,方便开发者定位分析。可通过gc-long-paused-time进行配置

其他:新增单VM内ArrayBuffer的native总内存上限为4GB

GC流程

HPPGC

Young GC

  • 触发机制: 年轻代GC触发阈值在2MB-16MB变化,根据分配速度和存活率等会变化。
  • 说明: 主要回收semi space新分配的年轻代对象。
  • 场景: 前台场景
  • 日志关键词: [ HPP YoungGC ]

Old GC

  • 触发机制: 老年代GC触发阈值在20MB-300多MB变化,大部分情况,第一次Old GC的阈值在20M左右,之后会根据对象存活率,内存占用大小进行阈值调整。
  • 说明: 对年轻代和部分老年代空间做整理压缩,其他空间做sweep清理。触发频率比年轻代GC低很多,由于会做全量mark,因此GC时间会比年轻代GC长,单次耗时约5ms~10ms。
  • 场景: 前台场景
  • 日志关键词:[ HPP OldGC ]

Full GC

  • 触发机制: 不会由内存阈值触发。应用切换后台之后,如果预测能回收的对象尺寸大于2M会触发一次Full GC。DumpHeapSnapshot 和 AllocationTracker 工具默认会触发Full GC。Native 接口和JS/TS 也有接口可以触发。
  • 说明: 会对年轻代和老年代做全量压缩,主要用于性能不敏感场景,最大限度回收内存空间。
  • 场景: 后台场景
  • 日志关键词:[ CompressGC ]

此后的Smart GC或者 IDLE GC 都是在上述三种GC中做选择。

触发策略

空间阈值触发GC

  • 函数方法:AllocateYoungOrHugeObject,AllocateHugeObject,等分配函数
  • 限制参数:对应的空间阈值
  • 说明:对象申请空间到达对应空间阈值时触发GC
  • 典型日志:日志可区分GCReason::ALLOCATION_LIMIT

native绑定大小达到阈值触发GC

  • 函数方法:GlobalNativeSizeLargerThanLimit
  • 限制参数:globalSpaceNativeLimit
  • 说明:影响是否进行全量mark,以及是否开始并发mark

切换后台触发GC

  • 函数方法:ChangeGCParams

  • 说明:切换后台主动触发一次Full GC

  • 典型日志:app is inBackground,app is not inBackground

    GC 日志中可区分GCReason::SWITCH_BACKGROUND

执行策略

ConcurrentMark

  • 函数方法:TryTriggerConcurrentMarking
  • 说明:尝试触发并发mark,将遍历对象进行标记的任务交由线程池中并发运行,减少主线程挂起时间。
  • 典型日志:fullMarkRequested, trigger full mark.,Trigger the first full mark,Trigger full mark,Trigger the first semi mark,Trigger semi mark

new space GC前后的阈值调整

  • 函数方法:AdjustCapacity
  • 说明: 在GC后调整SemiSpace触发水线,优化空间结构。
  • 典型日志:无直接日志,可以通过GC统计日志看出,GC前 young space 的阈值有动态调整。

第一次OldGC后阈值的调整

  • 函数方法:AdjustOldSpaceLimit
  • 说明:根据最小增长步长以及平均存活率调整OldSpace阈值限制
  • 典型日志:"AdjustOldSpaceLimit oldSpaceAllocLimit_: " << oldSpaceAllocLimit << " globalSpaceAllocLimit_: " << globalSpaceAllocLimit_;

第二次及以后的OldGC对old Space/global space阈值调整,以及增长因子的调整

  • 函数方法:RecomputeLimits
  • 说明:根据当前GC统计的数据变化重新计算调整newOldSpaceLimit,newGlobalSpaceLimit,globalSpaceNativeLimit和增长因子
  • 典型日志:“RecomputeLimits oldSpaceAllocLimit_: " << newOldSpaceLimit_ << " globalSpaceAllocLimit_: " << globalSpaceAllocLimit_ << " globalSpaceNativeLimit_:” << globalSpaceNativeLimit_;

PartialGC的Cset 选择策略

  • 函数方法:OldSpace::SelectCSet()

  • 说明:PartialGC执行时采用该策略选择存活对象数量少,回收代价小的Region优先进行GC。

  • 典型日志:Select CSet failure: number is too few,

    "Max evacuation size is 6_MB. The CSet region number: " << selectedRegionNumber;,

    "Select CSet success: number is " << collectRegionSet_.size();

特性

Smart GC

特性介绍

在应用性能敏感场景,通过将js线程(SmartGC对worker线程和taskpool线程不生效)GC触发水线临时调整到js堆最大值(js线程默认448MB),尽量避免触发GC导致应用掉帧。如果敏感场景持续时间过久,对象分配已经达到了堆最大值,则还是会触发GC,且这次GC由于积累的对象太多,GC时间会相对较久。

支持敏感场景

  • 应用冷启动(默认支持)
  • 应用滑动
  • 应用点击页面跳转
  • 超长帧

除应用冷启动是默认支持,其他敏感场景均为调用dfxjsnapi接口进行设置且无本质区别。

日志关键词: “SmartGC”

交互流程

标记性能敏感场景,在进入和退出性能敏感场景时,在堆上标记,避免不必要的GC,维持高性能表现。

IDLE GC

利用系统绘帧过程中存在的线程idletime,高效利用计算资源分段完成完整的GC工作,减少后续累积内存占用触发长GC造成的卡顿。

Incremental Mark

完成old gc通常需要消耗较多时间,一次idle time很难完成此项任务,因此将mark过程分布在多次idle time中完成。

在线性空间扩容时尝试进行Incremental Mark,满足以下条件则触发增量标记:

  • 在ArkProperties里打开ENABLE_IDLE_GC且收到了元能力发送的idleTime开关回调函数;
  • 当前无idleTask且未触发ConcurrentMark;
  • 增量标记完成时,堆大小距到达水线小于256K;
  • 增量标记期间分配对象大小小于100_KB

注:Incremental Mark与Full ConcurrentMark互斥。线性空间主要指的是semiSpace。

Idle YoungGC

在线性空间扩容时尝试进行Idle Collection,满足以下条件则设置相应的IdleTask:

  • 在ArkProperties里打开ENABLE_IDLE_GC且收到了元能力发送的idleTime开关回调函数;
  • 当前无idleTask且未触发ConcurrentMark;
  • 堆大小小于触发YoungGC ConcurrentMark水线256K以内;

注:Idle YoungGC可与ConcurrentMark共存(防止还未接收到IdleTime就达到GC水线),可先触发ConcurrentMark,后开始Idle YoungGC.

GC开发者调试接口

注意
以下接口仅供调试使用,非正式对外SDK接口,不应在应用正式版本中使用。

ArkTools.hintGC()

  • 调用方式:ArkTools.hintGC()
  • 接口类型:js接口
  • 作用:调用后由VM主动触发判断当前是否适合进行一次full GC。后台场景、内存预期存活率低于设定值,则会触发,判断为敏感状态则不会触发。
  • 使用场景:开发者提示系统进行GC
  • 典型日志:无直接日志,仅可区分外部触发(GCReason::EXTERNAL_TRIGGER)

ArkTools.forceFullGC()

  • 调用方式:ArkTools.forceFullGC()
  • 接口类型:js接口
  • 作用:直接触发一次GC,当前线程的local heap触发Full GC,shared heap触发Shared GC。
  • 使用场景:大桌面,开发者调试
  • 典型日志:无直接日志,仅可区分外部触发(GCReason::EXTERNAL_TRIGGER)

使用参考

// 首先需要声明接口
declare class ArkTools {
     static forceFullGC(): void;
     static hintGC(): void;
}

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';
  build() {
  Row() {
    Column() {
      Text(this.message)
        .fontSize(50)
        .fontWeight(FontWeight.Bold)
  
      Button("触发FullGC").onClick((event: ClickEvent) => {
          ArkTools.forceFullGC();  //方法内直接调用
      })
     Button("触发HintGC").onClick((event: ClickEvent) => {
         ArkTools.hintGC();  //方法内直接调用
     })
    }
    .width('100%')
  }
  .height('100%')
}
}

鸿蒙全栈开发全新学习指南

为了积极培养鸿蒙生态人才,让大家都能学习到鸿蒙开发最新的技术,针对一些在职人员、0基础小白、应届生/计算机专业、鸿蒙爱好者等人群,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线【包含了大厂APP实战项目开发】

本路线共分为四个阶段:

第一阶段:鸿蒙初中级开发必备技能

在这里插入图片描述

第二阶段:鸿蒙南北双向高工技能基础:gitee.com/MNxiaona/733GH

第三阶段:应用开发中高级就业技术

第四阶段:全网首发-工业级南向设备开发就业技术:gitee.com/MNxiaona/733GH

鸿蒙开发面试真题(含参考答案):gitee.com/MNxiaona/733GH

写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:gitee.com/MNxiaona/733GH

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1870494.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springcloud-config 客户端启用服务发现client的情况下使用metadata中的username和password

为了让spring admin 能正确获取到 spring config的actuator的信息&#xff0c;在eureka的metadata中添加了metadata.user.user metadata.user.password eureka.instance.metadata-map.user.name${spring.security.user.name} eureka.instance.metadata-map.user.password${spr…

Java中的程序异常处理介绍

一、异常处理机制 Java提供了更加优秀的解决办法&#xff1a;异常处理机制。 异常处理机制能让程序在异常发生时&#xff0c;按照代码的预先设定的异常处理逻辑&#xff0c;针对性地处理异常&#xff0c;让程序尽最大可能恢复正常并继续执行&#xff0c;且保持代码的清晰。 Ja…

Spring事务的源码底层实现

文章目录 事务理论执行过程EnableTransactionManagement底层实现 事务 在线流程图 理论执行过程 通过事务管理器创建一个连接对象connection1设置事务隔离级别、是否只读等conn1.autocommit(false)将conn1存入ThreadLocal中Map<DataSource,Connection>执行目标方法、多…

c++习题01-ljc的暑期兼职

目录 一&#xff0c;题目描述 二&#xff0c;思路 三&#xff0c;伪代码 四&#xff0c;流程图 五&#xff0c;代码 一&#xff0c;题目描述 二&#xff0c;思路 1&#xff0c;根据题目要求需要声明4个变量&#xff1a;a,b,c,d ;牛奶价格a&#xff0c;活动要求b&…

浅析Resource Quota中limits计算机制

前言 在生产环境中&#xff0c;通常需要通过配置资源配额&#xff08;Resource Quota&#xff09;来限制一个命名空间&#xff08;namespace&#xff09;能使用的资源量。在资源紧张的情况下&#xff0c;常常需要调整工作负载&#xff08;workload&#xff09;的请求值&#xf…

java基于ssm+jsp 毕业生就业信息管理系统

1管理员功能模块 管理员输入个人的用户名、密码、角色登录系统&#xff0c;这时候系统的数据库就会在进行查找相关的信息&#xff0c;如果我们输入的用户名、密码不正确&#xff0c;数据库就会提示出错误的信息提示&#xff0c;同时会提示管理员重新输入自己的用户名、密码&am…

MYSQL存储过程的创建

关于存储过程的题目 1、创建存储过程,查看user表中的所有数据 2、创建存储过程avg_order_quantity,返回所有订单的平均工资 3、创建存储过程show_max_bprice,用来查看bookS的单价最贵的价格 4、创建存储过程show_min_bprice,用来查看bookS的单价最低的价格&#xff0c;并将…

JS在线加密简述

JS在线加密&#xff0c;是指&#xff1a;在线进行JS代码混淆加密。通过混淆、压缩、加密等手段&#xff0c;使得JS源代码难以阅读和理解。从而可以有效防止代码被盗用或抄袭&#xff0c;保护开发者的知识产权和劳动成果。常用的JS在线加密网站有&#xff1a;JShaman、JS-Obfusc…

美业管理系统的优势和功能分析,美业系统你选对了吗?Java源码/演示视频分享

在当今竞争激烈的美业市场中&#xff0c;有效的管理对于提高效率、增强客户体验和推动业务增长至关重要。美业管理系统通过其各种功能和优势&#xff0c;成为现代美业企业不可或缺的利器。 本文将探讨美业管理系统的优势和功能&#xff0c;以及它们对美业企业的重要性。 1.预…

来聊聊Redis客户端的概念

写在文章开头 对于每一个建立的连接redis都会通过redisClient来管理建立的socket连接的信息&#xff0c;本文将从源码的分析的角度来剖析的Redis客户端的基本设计和实现。 Hi&#xff0c;我是 sharkChili &#xff0c;是个不断在硬核技术上作死的 java coder &#xff0c;是 C…

通信协议总结

IIC 基本特点 同步&#xff0c;半双工 标准100KHz&#xff0c;最高400KHz&#xff08;IIC主要应用于低速设备&#xff09; 硬件组成 需外接上拉电阻 通信过程 空闲状态 SDA和SCL都处于高电平 开始信号S和终止信号P 在数据传输过程中&#xff0c;当SCL0时&#xff0c;SDA才…

mac14.1.2 M1芯片终端使用brew命令提示“zsh- command not found- brew ”解决方案

mac14.1.2 M1芯片终端使用brew命令提示“zsh- command not found- brew ” 原因&#xff1a;brew默认安装目录在/opt/homebrew/bin&#xff0c;zshrc文件中找不到对应的PATH路径导致。&#xff08;可通过右键finder的图标选择「前往文件”-输入/opt/homebrew/bin」来查看brew是…

【图书推荐】CPython设计与实现“适合所有Python工程师阅读的书籍”

目录 一、图书推荐 |【CPython设计与实现】 1.1、书籍介绍 1.2、内容简介 1.3、适合哪些人阅读 1.4、作者译者简介 1.5、购买链接 一、图书推荐 |【CPython设计与实现】 "深入Python核心&#xff0c;揭秘CPython的设计智慧&#xff01;&#x1f4d6; 对于每一位热衷…

超详细的Pycharm使用虚拟环境搭建Django项目并创建新的虚拟环境教程

一、什么是虚拟环境&#xff1f; 通过软件虚拟出来的开发环境&#xff0c;不是真实存在的&#xff0c;一般在多套环境开发时会用到。 二、为什么要使用虚拟环境&#xff1f; 虚拟环境为不同的项目创建不同的开发环境&#xff0c;开发环境内所有使用的工具包互不影响。比如项…

初探 YOLOv8(训练参数解析)

文章目录 1、前言2、Backbone网络3、YOLOv8模型训练代码3.1、模型大小选择3.2、训练参数设置 4、训练参数说明5、目标检测系列文章 1、前言 YOLO 因为性能强大、消耗算力较少&#xff0c;一直以来都是实时目标检测领域的主要范式。该框架被广泛用于各种实际应用&#xff0c;包…

Linux C 程序 【02】创建线程

1.开发背景 上一个篇章&#xff0c;基于 RK3568 平台的基础上&#xff0c;运行了最简单的程序&#xff0c;然而我们使用了 Linux 系统&#xff0c;系统自带的多线程特性还是比较重要的&#xff0c;这个篇章主要描述线程的创建。 2.开发需求 设计实验&#xff1a; 创建一个线程…

线性相关,无关?秩?唯一解(只有零解),无穷解(有非零解)?D=0,D≠0?

目录 线性有关无关 和 唯一解&#xff08;只有零解&#xff09;&#xff0c;无穷解&#xff08;有非零解&#xff09;之间的关系 D0&#xff0c;D≠0&#xff1f; 和 秩 的关系 串起来&#xff1a; 线性相关&#xff0c;无关&#xff1f;秩&#xff1f;唯一解&#xff08;只…

【M365运维】Outlook和Teams里不显示用户的组织架构

【问题】 由于一些误操作&#xff0c;把用户账户禁用并重新启用后&#xff0c;发现在Outlook和Teams里无法查看用户的组织结构图了。如下图所示&#xff1a; - 在Outlook 里&#xff0c;用户标签页的组织一直显示“正在加载..."&#xff0c;成员身份也是“找不到任何组。…

卸载vmware时2503,2502报错的解决办法

1.背景 windows 卸载vmware时&#xff0c;显示2503报错&#xff0c;无法完全卸载 2. 解决方案 2.1 参考安装报错2502&#xff0c;2503的处理方式 文献&#xff1a;https://blog.csdn.net/zhangvalue/article/details/80309828 2.1 步骤&#xff1a; 2.1.1 cmd 管理员打开…

O_CREAT创建函数的例子

代码&#xff1a; #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> int main(void) {int fd-1;char filename[]"test.txt";fdopen(filename,O_RDWR|O_CREAT|O_EXCL,S_IRWXU);if(-1fd){printf("F…