From a102ce3ca077ea5c9bd74826070ce5857eba9e20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E5=8F=81=E7=8E=96?= Date: Tue, 3 Jun 2025 10:35:22 +0800 Subject: [PATCH] =?UTF-8?q?CG=E5=9E=83=E5=9C=BE=E5=9B=9E=E6=94=B6AI?= =?UTF-8?q?=E6=89=AB=E6=8F=8F=E6=8A=A5=E5=91=8A=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 林叁玖 --- .../arkts-utils/gc-introduction.md | 78 +++++++++---------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/zh-cn/application-dev/arkts-utils/gc-introduction.md b/zh-cn/application-dev/arkts-utils/gc-introduction.md index a647f6d9474..38d38cb81e9 100644 --- a/zh-cn/application-dev/arkts-utils/gc-introduction.md +++ b/zh-cn/application-dev/arkts-utils/gc-introduction.md @@ -8,10 +8,10 @@ GC(全称 Garbage Collection),即垃圾回收。在计算机领域,GC是 #### 引用计数 -当对象B指向对象A时,A的引用计数加1;当该指向断开时,A的引用计数减1。如果A的引用计数为0,回收对象A。 +当对象B指向对象A时,A的引用计数加1;指向断开时,A的引用计数减1。若A的引用计数为0,回收对象A。 -- 优点:引用计数算法设计简单,内存回收及时,在对象成为垃圾时立即回收,因此无需引入单独的暂停业务代码(Stop The World,STW)阶段。 -- 缺点:对对象操作时插入计数环节,增加了内存分配和赋值的开销,影响程序性能。更严重的是存在由循环引用导致的内存泄漏问题。 +- 优点:设计简单,内存回收及时,在对象成为垃圾时立即回收,因此无需引入单独的暂停业务代码(Stop The World,STW)阶段。 +- 缺点:对对象进行操作时插入计数环节会增加内存分配和赋值的开销,影响程序性能。更严重的是,循环引用可能导致内存泄漏。 ``` class Parent { constructor() { @@ -39,11 +39,11 @@ function main() { ![image](./figures/tracing-gc.png) -根对象包括程序运行中的栈内对象和全局对象等当前时刻一定存活的对象。被根对象引用的对象也是存活状态。通过遍历可以找到所有存活的对象。如图所示,从根对象开始遍历对象及其域,所有可达的对象标记为蓝色,即为活对象;剩下的不可达对象标记为黄色,即为垃圾。 -- 优点:对象追踪算法可以解决循环引用的问题,且对内存的分配和赋值没有额外的开销。 -- 缺点:和引用计数算法相反,对象追踪算法较为复杂,且有短暂的STW阶段。此外,回收会有延迟,导致比较多的浮动垃圾。 +根对象包括程序运行中的栈内对象和全局对象等当前时刻一定存活的对象。被根对象引用的对象也是存活状态。通过遍历根对象可以找到所有存活的对象。如图所示,从根对象开始遍历对象及其域,所有可达的对象标记为蓝色,即为活对象;剩下的不可达对象标记为黄色,即为垃圾。 +- 优点:可以解决循环引用问题,且对内存的分配和赋值没有额外的开销。 +- 缺点:算法复杂,且有短暂的暂停业务代码STW阶段。此外,回收会有延迟,导致比较多的浮动垃圾。 -引用计数和对象追踪算法各有优劣。由于引用计数存在内存泄漏问题,ArkTS运行时选择基于对象追踪(即Tracing GC)算法设计GC。 +引用计数和对象追踪算法各有优劣。由于引用计数存在内存泄漏,ArkTS运行时选择基于对象追踪(即Tracing GC)算法设计GC。 ### 对象追踪的三种类型 @@ -53,29 +53,29 @@ function main() { ![image](./figures/mark-clearn.png) -完成对象图遍历后,擦除不可达对象内容,并将其放入空闲队列,以便下次对象分配。 -该回收方式不搬移对象,因此效率高。但因回收对象内存地址不连续,会导致内存碎片化,降低分配效率。极端情况下,即使有大量空闲内存,也可能无法放入较大的对象。 +完成对象图遍历后,擦除不可达对象,并将其放入空闲队列,以便下次分配。 +该回收方式不搬移对象,因此效率高。但回收对象内存地址不连续,会导致内存碎片化,降低分配效率。极端情况下,即使有大量空闲内存,也可能无法分配较大对象。 #### 标记-复制回收 ![image](./figures/mark-copy.png) -遍历对象图时,将可达对象复制到新内存空间。遍历完成后,一次回收旧内存空间。 -这种方式可以解决内存碎片问题,并通过一次遍历完成整个GC过程,效率较高。但在极端情况下,需要预留一半的内存空间以确保所有活动对象可以被拷贝,导致空间利用率较低。 +遍历对象图时,将可达对象复制到新内存空间。遍历完成后,一次回收旧内存空间。 +这种方式可以解决内存碎片问题,通过一次遍历完成整个GC过程,效率较高。但在极端情况下,需要预留一半的内存空间以确保所有活动对象可以被拷贝,导致空间利用率较低。 #### 标记-整理回收 ![image](./figures/mark-shuffle.png) -完成对象图遍历后,将可达对象(蓝色)往本区域(或指定区域)的头部空闲位置复制,然后将已经完成复制的对象回收整理到空闲队列中。 -这种回收方式既解决了“标记-清扫回收”导致的大量内存碎片问题,同时避免了“标记-复制回收”浪费一半内存空间的缺点,但性能开销比“标记-复制回收”高。 +完成对象图遍历后,将可达对象(蓝色)复制到本区域或指定区域的头部空闲位置,然后将已复制的对象回收到空闲队列中。 +这种回收方式解决了“标记-清扫回收”导致的大量内存碎片问题,避免了“标记-复制回收”浪费一半内存空间的缺点,但性能开销比“标记-复制回收”高。 ### HPP GC HPP GC(High Performance Partial Garbage Collection),即高性能部分垃圾回收,其中“High Performance”主要体现在三方面,分代模型、混合算法和GC流程优化。在算法方面,HPP GC会根据不同对象区域、采取不同的回收方式。 #### 分代模型 -ArkTS运行时采用传统的分代模型,将对象进行分类。考虑到大多数新分配的对象都会在一次GC之后被回收,而大多数经过多次GC之后依然存活的对象会继续存活,ArkTS运行时将对象划分为年轻代对象和老年代对象,并将对象分配到不同的空间。 +ArkTS运行时采用分代模型,将对象划分为年轻代和老年代,并分别分配到对应的空间中。大多数新分配的对象会在一次GC后被回收,而多次GC后仍存活的对象会被划入老年代。 ![image](./figures/generational-model.png) @@ -86,23 +86,23 @@ ArkTS运行时将新分配的对象直接分配到年轻代(Young Space)的F HPP GC是部分复制、部分整理和部分清扫的混合算法,根据年轻代和老年代对象特点采取不同的回收方式。 - 部分复制 -考虑到年轻代对象生命周期短、回收频繁且大小有限,ArkTS运行时对年轻代对象采用“标记-复制回收”算法。 +年轻代对象生命周期短,回收频繁且大小有限,ArkTS运行时对年轻代对象采用“标记-复制回收”算法。 - 部分整理+部分清扫 -根据老年代对象的特点,引入启发式Collection Set(简称CSet)选择算法。此选择算法的基本原理是:在标记阶段对每个区域的存活对象进行大小统计,然后在回收阶段优先选出存活对象少、回收代价小的区域进行对象整理回收,再对剩下的区域进行清扫回收。 +根据老年代对象的特点,引入启发式Collection Set(简称CSet)选择算法。该算法在标记阶段统计每个区域的存活对象大小,回收阶段优先选择存活对象少、回收代价小的区域进行整理回收,最后清扫剩余区域。 回收策略如下: -- 根据设定的区域存活对象大小阈值,将满足条件的区域纳入初步的CSet队列,并根据存活率进行从低到高的排序(注:存活率=存活对象大小/区域大小)。 +- 根据设定的区域存活对象大小阈值,将满足条件的区域纳入初步的CSet队列,并按存活率从低到高排序(存活率=存活对象大小/区域大小)。 - 根据设定的释放区域个数阈值,选出最终的CSet队列,进行整理回收。 - 对未被选入CSet队列的区域进行清扫回收。 -启发式CSet选择算法结合了“标记-整理回收”和“标记-清扫回收”算法的优点,避免了内存碎片问题,同时提升了性能。 +启发式CSet选择算法结合了“标记-整理回收”和“标记-清扫回收”算法的优点,避免了内存碎片问题,提升了性能。 #### 流程优化 -HPP GC流程中引入了大量的并发和并行优化,以减少对应用性能的影响。采用了并发+并行标记(Marking)、并发+并行清扫(Sweep)、并行复制/整理(Evacuation)、并行回改(Update)和并发清理(Clear)执行GC任务。 +HPP GC流程中引入大量的并发和并行优化,减少对应用性能的影响。优化措施包括并发+并行标记(Marking)、并发+并行清扫(Sweep)、并行复制/整理(Evacuation)、并行回改(Update)和并发清理(Clear)执行GC任务。 ## Heap结构及其配置参数 @@ -126,7 +126,7 @@ HPP GC流程中引入了大量的并发和并行优化,以减少对应用性 > > 以下参数未提示可配置的均为不可配置项,由系统自行设定。 -根据系统分配堆空间总大小64MB-128MB/128MB-256MB/大于256MB的三个范围,以下参数系统会设置不同的大小。如果表格内范围仅有一个值,则表示该参数值不随堆空间总大小变化。手机设备堆空间总大小默认为大于256MB。 +根据系统分配的堆空间总大小,分为64MB-128MB/128MB-256MB/大于256MB的三个范围,系统会为以下参数设置不同的值。如果表格内范围仅有一个值,则表示该参数值不随堆空间总大小变化。手机设备堆空间总大小默认为大于256MB。 开发者可以查阅[hidebug接口文档](../reference/apis-performance-analysis-kit/js-apis-hidebug.md),使用相关接口查询内存信息。 #### 堆大小相关参数 @@ -145,7 +145,7 @@ HPP GC流程中引入了大量的并发和并行优化,以减少对应用性 | HeapSize | 768 MB | worker类型线程堆空间大小。 | #### Semi Space -heap中生成两个Semi Space供copying使用。 +在heap中生成两个Semi Space,用于copying操作。 | 参数名 | 范围 | 作用 | | --- | --- | --- | | semiSpaceSize | 2MB-4MB/2MB-8MB/2MB-16MB | SemiSpace空间大小,会根据堆总大小有不同的范围限制。 | @@ -153,7 +153,7 @@ heap中生成两个Semi Space供copying使用。 | semiSpaceStepOvershootSize| 2MB | 允许过冲最大大小。 | #### Old Space 和 Huge Object Space -初始化时均设定为Heap剩余未分配空间的大小,默认手机设备主线程OldSpaceSize上限接近350MB。 +初始化时,Old Space和Huge Object Space的大小均设定为Heap剩余未分配空间的大小。默认手机设备主线程OldSpaceSize上限接近350MB。 | 参数名 | 范围 | 作用 | | --- | --- | --- | @@ -178,19 +178,19 @@ heap中生成两个Semi Space供copying使用。 | 参数名 | 值 | 作用 | | --- | --- | --- | -| gcThreadNum | 7 | gc线程数量,默认为7。可通过`gc-thread-num`参数自行设定该参数值。 | +| gcThreadNum | 7 | gc线程数量,默认值为7。可通过`gc-thread-num`参数设置。 | | MIN_TASKPOOL_THREAD_NUM | 3 | 线程池最小线程数。 | | MAX_TASKPOOL_THREAD_NUM | 7 | 线程池最大线程数。 | -注:该线程池主要用于执行GC流程中的并发任务。线程池初始化时,会综合参考gcThreadNum和线程数的上下限。如果gcThreadNum为负值,线程池的线程数将初始化为CPU核心数的一半。 +注:该线程池主要用于执行GC流程中的并发任务,初始化时会参考gcThreadNum和线程数的上下限。如果gcThreadNum为负值,线程池的线程数将初始化为CPU核心数的一半。 #### 其他参数 | 参数名 | 值 | 作用 | | --- | --- | --- | -| minAllocLimitGrowingStep | 2M/4M/8M | heap整体重新计算空间大小限制时,控制oldSpace、heapObject和globalNative的最小增长步长。 | +| minAllocLimitGrowingStep | 2M/4M/8M | 重新计算heap整体空间大小时,控制oldSpace、heapObject和globalNative的最小增长步长。 | | minGrowingStep | 4M/8M/16M | 调整oldSpace的最小增长步长。 | -| longPauseTime | 40ms | 判断是否为超长GC界限,超长GC会触发完整GC日志信息打印,方便开发者定位分析。可通过`gc-long-paused-time`进行配置。 | +| longPauseTime | 40ms | 判断是否为超长GC的界限。超长GC会触发完整GC日志信息的打印,方便开发者定位和分析。可通过`gc-long-paused-time`进行配置。 | ## GC流程 @@ -200,14 +200,14 @@ heap中生成两个Semi Space供copying使用。 #### Young GC -- **触发机制**:年轻代GC触发阈值在2MB-16MB变化,根据分配速度和存活率等会变化。 +- **触发机制**:年轻代GC触发阈值在2MB-16MB变化,根据分配速度和存活率调整。 - **说明**:主要回收semi space新分配的年轻代对象。 - **场景**:前台场景。 - **日志关键词**:`[ HPP YoungGC ]` #### Old GC -- **触发机制**:老年代GC触发阈值在20MB-300多MB变化,大部分情况,第一次Old GC的阈值在20M左右,之后会根据对象存活率,内存占用大小进行阈值调整。 +- **触发机制**:老年代GC触发阈值在20MB至300MB之间变化,第一次Old GC的阈值在20M左右,之后会根据对象存活率和内存占用情况进行调整。 - **说明**:对年轻代和部分老年代空间做整理压缩,其他空间做sweep清理。触发频率比年轻代GC低很多,由于会做全量mark,因此GC时间会比年轻代GC长,单次耗时约5ms~10ms。 - **场景**:前台场景。 - **日志关键词**:`[ HPP OldGC ]` @@ -219,7 +219,7 @@ heap中生成两个Semi Space供copying使用。 - **场景**:后台场景。 - **日志关键词**:`[ CompressGC ]` -此后的Smart GC或IDLE GC都会从上述三种GC中选择。 +此后,Smart GC和IDLE GC将从上述三种GC中选择。 ### 触发策略 @@ -227,19 +227,19 @@ heap中生成两个Semi Space供copying使用。 - 函数方法:`AllocateYoungOrHugeObject`,`AllocateHugeObject`等分配函数。 - 限制参数:对应的空间阈值。 -- 说明:对象申请空间到达对应空间阈值时触发GC。 +- 说明:对象申请空间到达阈值时触发GC。 - 典型日志:日志可区分GCReason::ALLOCATION_LIMIT。 #### native绑定大小达到阈值触发GC - 函数方法:`GlobalNativeSizeLargerThanLimit` - 限制参数:`globalSpaceNativeLimit`。 -- 说明:影响是否进行全量mark,以及是否开始并发mark。 +- 说明:影响是否进行全量mark和开始并发mark。 #### 切换后台触发GC - 函数方法:`ChangeGCParams` -- 说明:切换后台后主动触发一次Full GC。 +- 说明:切换后台后主动触发Full GC。 - 典型日志:`app is inBackground` 和 `app is not inBackground`。 GC 日志中可区分GCReason::SWITCH_BACKGROUND。 @@ -297,7 +297,7 @@ heap中生成两个Semi Space供copying使用。 #### 特性介绍 -在应用性能敏感场景,通过将线程(SmartGC对worker线程和taskpool线程不生效)GC触发水线临时调整到线程的堆最大值(主线程线程默认448MB),尽量避免触发GC导致应用掉帧。如果敏感场景持续时间过久,对象分配已经达到了堆最大值,则还是会触发GC,且这次GC由于积累的对象太多,GC时间会相对较久。 +在应用性能敏感场景中,通过将线程(SmartGC对worker线程和taskpool线程不生效)GC触发水线临时调整到线程的堆最大值(主线程线程默认448MB),尽量避免GC导致应用掉帧。如果敏感场景持续时间过长,对象分配达到堆最大值,仍会触发GC,且由于积累的对象较多,GC时间会相对较长。 #### 支持敏感场景 @@ -306,7 +306,7 @@ heap中生成两个Semi Space供copying使用。 - 应用点击页面跳转。 - 超长帧。 -当前该特性使能由系统侧进行管控,三方应用暂无接口直接调用。 +当前该特性的使能由系统侧进行管控,第三方应用暂无接口直接调用。 日志关键词: `SmartGC`。 @@ -314,13 +314,13 @@ heap中生成两个Semi Space供copying使用。 ![image](./figures/gc-smart-feature.png) -标记性能敏感场景,在进入和退出性能敏感场景时,在堆上标记,避免不必要的GC,维持高性能表现。 +在性能敏感场景中,进入和退出时进行堆标记,避免不必要的GC,保持高性能。 ## 日志解释 ### 开启全量日志 -默认情况下,详细的GC日志仅在GC耗时超过40毫秒时才会打印。若需开启所有GC执行的日志,需使用命令在设备中开启。 +默认情况下,详细的GC日志仅在GC耗时超过40毫秒时才会打印。若需记录所有GC执行的日志,需在设备中使用相应命令开启。 **使用样例:** @@ -395,15 +395,15 @@ C03F00/ArkCompiler: Heap average alive rate: 0.635325 > **注意:** > -> 以下接口仅供调试使用,非正式对外SDK接口,不应在应用正式版本中使用。 +> 以下接口仅供调试使用,非正式SDK接口,不应在正式版本中使用。 ### ArkTools.hintGC() - 调用方式:`ArkTools.hintGC()` - 接口类型:ArkTS接口。 - 作用:调用后,VM主动判断是否适合进行full GC。如果后台场景中内存预期存活率低于设定值,则触发full GC;若判断为敏感状态,则不触发。 -- 使用场景:开发者提示系统进行GC。 -- 典型日志:无直接日志,仅可区分外部触发(`GCReason::TRIGGER_BY_JS`)。 +- 使用场景:提示系统进行GC。 +- 典型日志:无直接日志,仅能区分外部触发(`GCReason::TRIGGER_BY_JS`)。 **使用参考:** -- Gitee