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

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.ppmy.cn/embedded/53979.html

相关文章

Python使用策略模式绘制图片分析多组数据

趋势分析&#xff1a;折线图静态比较&#xff1a;条形图分布分析&#xff1a;箱线图离散情况&#xff1a;散点图 import matplotlib.pylab as plt from abc import ABC, abstractmethod import seaborn as sns import pandas as pd import plotly.graph_objects as go import p…

【系统架构设计师】计算机组成与体系结构 ③ ( 层次化存储结构 | 寄存器 | 高速缓存 | 内存 | 外存 )

文章目录 一、层次化存储结构1、层次化存储结构2、层次化存储结构 - 示例说明3、程序员可操作的部分 计算机 采用 分级存储结构 , 主要目的是 为了 解决 容量 / 价格 / 速度 之间的矛盾 ; 一、层次化存储结构 1、层次化存储结构 计算机 存储器 按照存储速度 由快到慢 进行排序 …

零基础入门办公软件速成学习 沈阳电脑办公软件培训

专业指导&#xff1a;由专业的培训师或讲师提供指导&#xff0c;确保员工能够全面、系统地学习软件的各种功能和技巧。 定制课程&#xff1a;根据公司需求和员工现有水平定制课程内容&#xff0c;确保培训的针对性和实用性。 互动学习&#xff1a;通过实时演示、练习和答疑环节…

什么是torchrun?

torchrun 是 PyTorch 用于分布式训练的命令行工具&#xff0c;旨在简化启动和管理分布式训练任务的过程。下面我将详细讲解 torchrun 的使用方法&#xff0c;并讨论它与分布式数据并行&#xff08;Distributed Data Parallel, DDP&#xff09;的区别。 一、torchrun的使用方法…

个人网站搭建-步骤(持续更新)

域名申请 域名备案 域名解析 服务器购买 端口转发 Nginx要在Linux上配置Nginx进行接口转发&#xff0c;您可以按照以下步骤进行操作&#xff1a; 安装Nginx&#xff08;如果尚未安装&#xff09;&#xff1a; 使用包管理工具&#xff08;如apt, yum, dnf, 或zypper&#x…

IOS Swift 从入门到精通:从 JSON 文件加载数据

文章目录 常见问题解答数据模型JSON 数据验证 JSON解码 JSON编写 FAQRow 代码添加状态栏背景模糊将内容添加到 FAQView常见问题解答数据模型 此 FAQ 模型符合Decodable,因为我们需要将 JSON 数据解码为 SwiftUI 数据。它还将符合 Identifiable ,因此我们稍后可以在 ForEach …

说一说ABAP CDS View的发展历史与特性

1. 背景 随着SAP Fiori应用程序的兴起&#xff0c;SAP领域的小伙伴接触和使用ABAP CDS View的机会也是越来越多。今天&#xff0c;让我们花些时间&#xff0c;一起在了解下这项技术的设计初衷和发展历史。 2. 设计初衷 说起ABAP CDS View&#xff0c;就不得不提及SAP HANA。…

【LeetCode面试经典150题】117. 填充每个节点的下一个右侧节点指针 II

一、题目 117. 填充每个节点的下一个右侧节点指针 II - 力扣&#xff08;LeetCode&#xff09; 给定一个二叉树&#xff1a; struct Node {int val;Node *left;Node *right;Node *next; } 填充它的每个 next 指针&#xff0c;让这个指针指向其下一个右侧节点。如果找不到下一个…

使用 Reqable 在 MuMu 模拟器进行App抓包(https)

1、为什么要抓包&#xff1f; 用开发手机应用时&#xff0c;查看接口数据不能像在浏览器中可以直接通过network查看&#xff0c;只能借助抓包工具来抓包&#xff0c;还有一些线上应用我们也只能通过抓包来排查具体的问题。 2、抓包工具 实现抓包&#xff0c;需要一个抓包工具…

Web3新视野:Lumoz节点的潜力与收益解读

摘要&#xff1a;低估值、高回报、无条件退款80%...... Lumoz正通过其 zkVerifier 节点销售活动&#xff0c;引领一场ZK计算革命。 长期以来&#xff0c;加密市场以其独特的波动性和增长潜力&#xff0c;持续吸引着全球投资者的目光。而历史数据表明&#xff0c;市场往往在一年…

Redis-主从复制-测试主从模式下的读写操作

文章目录 1、在主机6379写入数据2、在从机6380上写数据报错3、从机只能读数据&#xff0c;不能写数据 1、在主机6379写入数据 127.0.0.1:6379> keys * (empty array) 127.0.0.1:6379> set uname jim OK 127.0.0.1:6379> get uname "jim" 127.0.0.1:6379>…

【React】Axios请求头注入token

业务背景: Token作为用户的数据标识&#xff0c;在接口层面起到了接口权限控制的作用&#xff0c;也就是说后端有很多接口都需要通过查看当前请求头信息中是否含有token数据&#xff0c;来决定是否正常返回数据 // 添加请求拦截器 request.interceptors.request.use(config …

【日志消息类的编写】

日志消息类编写 由于上篇的代码比较简单&#xff0c;今天就多写两段代码顺便把日志消息类编写完成。 这个类的实现就是&#xff1a;什么时间&#xff0c;哪个线程&#xff0c;哪个文件的哪一行&#xff0c;发生了什么等级的日志&#xff0c;日志机器名字是什么&#xff0c;日…

国内AI行业对GPU算力的需求有多大?

随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;算力作为支撑其持续进步的核心动力&#xff0c;在国内的重要性日益凸显&#xff0c;无论是海外还是国内&#xff0c;AI算力行业都呈现出蓬勃发展的态势&#xff0c;而国内对于AI算力的需求更是呈现出爆发式的…

【仿真】UR机器人相机标定、立体标定、手眼标定、视觉追踪(双目)

实现在CoppeliaSim环境中进行手眼标定和目标追踪的一个例子。它主要涉及到机器人、机器视觉和控制算法的编程&#xff0c;使用了Python语言。接下来对该代码的主要类和方法进行解析&#xff1a; 1. 导入相关库 用于与CoppeliaSim模拟器通过ZeroMQ接口通信。包含Rotation类&…

探索AI的巅峰:详解GPT-3.5与GPT-4系列模型的区别

人工智能领域不断涌现出令人惊叹的技术突破&#xff0c;其中OpenAI的ChatGPT系列模型尤为引人注目。随着GPT-4的发布&#xff0c;技术开发者们对比分析其与前一代GPT-3.5的差异显得尤为重要。本文将深入探讨GPT-3.5和GPT-4系列模型的主要区别&#xff0c;帮助大家更好地理解和应…

深入探索:大型语言模型消除幻觉的解决之道

随着人工智能技术的飞速发展&#xff0c;大型语言模型&#xff08;LLMs&#xff09;已经成为自然语言处理领域的明星。它们以其庞大的知识库和生成连贯、上下文相关文本的能力&#xff0c;极大地推动了研究、工业和社会的进步。然而&#xff0c;这些模型在生成文本时可能会产生…

深入理解 JavaScript Promise

引言 在当今的 JavaScript 开发中&#xff0c;异步编程已经成为了标准实践。随着我们的应用程序变得越来越复杂&#xff0c;管理异步操作和回调变得尤为关键。在过去&#xff0c;开发者们常常发现自己陷入所谓的“回调地狱”&#xff0c;这是一种由于深层嵌套的回调函数导致的…

调和映照理论几个重要的基础理论

曲面Ricci流理论 曲面Ricci流理论&#xff08;Ricci Flow on Surfaces&#xff09;是一个重要的几何分析理论&#xff0c;研究流形上的Ricci流的演化。在数学领域&#xff0c;Ricci流是一种流形上的度量的演化过程&#xff0c;通过调整度量的曲率来研究流形的几何结构。曲面Ri…

Unity开发者转UE 新手必读

前言 本页面为熟悉Unity的用户概述了 虚幻引擎(UE)。如果你具备一些Unity知识&#xff0c;而且想学习如何运用自己所学的知识在虚幻引擎中工作&#xff0c;下面各小节将帮助你入门。 下面的截图并排显示了Unity和虚幻编辑器。各个区域采用相同的颜色来表示相同的功能。每个区…