• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# GC Introduction
2
3Garbage Collection (GC) is the process of finding garbage in memory and releasing and reclaiming memory space. Two GC algorithms are mainly used: reference counting and tracing GC. ArkTS runtime implements efficient memory reclamation in different scenarios based on generational models and hybrid algorithms.
4
5In ArkTS, data types are classified into simple type and reference type. Data of the simple type is stored in stacks, and its space is automatically allocated and reclaimed by the operating system. Data of the reference type is stored in heaps, and its space must be manually reclaimed by the engine. GC is a management mechanism for automatically reclaiming heap space.
6
7## Heap Space Structure and Parameters
8
9### Heap Space Structure
10
11![image](./figures/gc-heap-space.png)
12
13- Semi Space: stores young generation, that is, newly created objects, which may be short-lived. The copying algorithm is used to reclaim memory.
14- Old Space: stores old generation, that is, long-surviving objects. Multiple algorithms are used to reclaim memory based on scenarios.
15- Huge Object Space: stores huge objects. A separate region is used to store a huge object.
16- Read Only Space: stores read-only data at runtime.
17- Non-Movable Space: stores unmovable objects.
18- Snapshot Space: stores heap snapshots.
19- Machine Code Space: stores machine codes.
20
21Each space is divided into one or more regions for refined management. A region is the unit applied for from the memory allocator.
22
23### Parameters
24
25> **NOTE**
26>
27> Among all the parameters described in this section, if no description is provided for how to configure a parameter, then the parameter is automatically set by the system.
28
29For some of the parameters, three values or value ranges are provided, corresponding to the three value ranges of the total heap size: 64–128 MB/128–256 MB/ > 256 MB. If the remaining memory space is sufficient, the third value range (> 256 MB) is used by default.
30
31#### Parameters of Semi Space
32
33Two Semi Spaces are generated in the heap for the copying algorithm to use.
34
35| Parameter| Value or Value Range| Description|
36| --- | --- | :--- |
37| semiSpaceSize | 2–4 MB/2–8 MB/2–16 MB| Size of Semi Space. The value varies according to the total heap size.|
38| semiSpaceTriggerConcurrentMark | 1 M/1.5 M/1.5 M| Threshold for independently triggering the concurrent marking phase of Semi Space for the first time.|
39| semiSpaceStepOvershootSize| 2 MB | Maximum overshoot size of Semi Space.|
40
41#### Parameters of Other Spaces
42
43| Parameter| Value or Value Range| Description|
44| --- | --- | :--- |
45| defaultReadOnlySpaceSize | 256 KB | Default size of Read Only Space.|
46| defaultNonMovableSpaceSize | 2 MB/6 MB/64 MB | Default size of Non-Movable Space.|
47| defaultSnapshotSpaceSize | 512 KB/512 KB/ 4 MB | Default size of Snapshot Space.|
48| defaultMachineCodeSpaceSize | 2 MB/2 MB/8 MB | Default size of Machine Code Space.|
49
50#### Parameters of Old Space and Huge Object Space
51
52During initialization, the parameter is set to the size of the unallocated heap space left.
53
54| Parameter| Value or Value Range| Description|
55| --- | --- | :--- |
56| oldSpaceOvershootSize | 4 MB/8 MB/8 MB | Maximum overshoot size of Old Space.|
57
58#### Heap Size Parameters
59
60| Parameter| Value or Value Range| Description|
61| --- | --- | :--- |
62| HeapSize | 448–1024 MB | Total heap size. The actual size allocated varies according to the heap type. The lower limit is reduced in the case of an insufficient memory pool.|
63| SemispaceSize | 2–4 MB/2–8 MB/2–16 MB| Size of Semi Space.|
64| NonmovableSpaceSize | 2 MB/6 MB/64 MB | Size of Non-Movable Space.|
65| SnapshotSpaceSize | 512 KB| Size of Snapshot Space.|
66| MachineCodeSpaceSize | 2 MB| Size of Machine Code Space.|
67
68#### Maximum Number of Worker Thread Heaps
69
70| Parameter| Value or Value Range| Description|
71| --- | --- | --- |
72| heapSize  | 768 MB | Size of the heap space of the work type.|
73
74#### Size of the Interpreter Stack
75
76| Parameter| Value or Value Range| Description|
77| --- | --- | --- |
78| maxStackSize | 128 KB| Maximum frame size of the interpreter stack.|
79
80#### Concurrency Parameters
81
82| Parameter| Value| Description|
83| --- | ---: | --- |
84| gcThreadNum | 7 | Number of GC threads. The default value is 7. You can set this parameter using **gc-thread-num**.|
85| MIN_TASKPOOL_THREAD_NUM | 3 | Minimum number of threads in the thread pool.|
86| MAX_TASKPOOL_THREAD_NUM | 7 | Maximum number of threads in the thread pool.|
87
88Note: The thread pool is used to execute concurrent tasks in the GC process. During thread pool initialization, all the three parameters need to be considered. If **gcThreadNum** is a negative value, the number of threads in the initialized thread pool is the number of CPU cores divided by 2.
89
90#### Other Parameters
91
92| Parameter| Value| Description|
93| --- | --- | --- |
94| minAllocLimitGrowingStep | 2 M/4 M/8 M| Minimum increase step of **oldSpace**, **heapObject**, and **globalNative** when the heap space size is recalculated.|
95| minGrowingStep | 4 M/8 M/16 M | Minimum increase step of **oldSpace**.|
96| longPauseTime | 40 ms| Threshold for checking for a long GC pause. In the case of long GC pauses, complete GC log is printed, facilitating fault locating and analysis. You can set this parameter using **gc-long-paused-time**.|
97
98### Other
99
100### The maximum native memory of the ArrayBuffer in a single VM is 4 GB.
101
102## GC Process
103
104
105![image](./figures/gc-process.png)
106
107### HPP GC
108
109High Performance Partial Garbage Collection (HPP GC) achieves efficient garbage collection by employing generational models, hybrid algorithms, and GC process optimization.
110
111#### Young GC
112
113- **When to trigger**: The young GC trigger threshold ranges from 2 MB to 16 MB, depending on the allocation speed and survival rate.
114- **Description**: Reclaims the young-generation objects newly allocated to Semi Space.
115- **Scenario**: Foreground
116- **Log keywords**: [ HPP YoungGC ]
117
118#### Old GC
119
120- **When to trigger**: The old GC trigger threshold ranges from 20 MB to 300 MB. In most cases, the threshold of the first old GC is about 20 MB, and the threshold for subsequent old GC operations is adjusted based on the survival rate and memory usage.
121- **Description**: Sorts and compresses the space of the young generation and some space of the old generation, and sweeps other spaces. The trigger frequency is much lower than that of the young GC. Due to full marking, a single old GC operation takes about 5 ms to 10 ms, longer than that of the young GC.
122- **Scenario**: Foreground
123- **Log keywords**: [ HPP OldGC ]
124
125#### Full GC
126
127- **When to trigger**: Full GC is not triggered based on the memory threshold. After the application is switched to the background, full GC is triggered if the size of the object that can be reclaimed is expected to be greater than 2 MB. You can also trigger full GC using the DumpHeapSnapshot and AllocationTracker tools or calling native interfaces and JS/TS interfaces.
128- **Description**: Performs full compression on the young generation and old generation. Full GC is mainly used in performance-insensitive scenarios to reclaim memory space to the maximum extent.
129- **Scenario**: Background
130- **Log keywords**: [CompressGC]
131
132Smart GC or idle GC is based on these three GC modes.
133
134### Trigger Policy
135
136#### GC Triggered by Space Thread
137
138- Functions: **AllocateYoungOrHugeObject**, **AllocateHugeObject**, and other allocation-related functions
139- Restriction parameters: corresponding space thresholds
140- Description: GC is triggered when the space applied for by an object reaches the corresponding threshold.
141- Log keywords: **GCReason::ALLOCATION_LIMIT**
142
143#### GC Triggered by Native Binding Size
144
145- Functions: **GlobalNativeSizeLargerThanLimit**
146- Restriction parameters: **globalSpaceNativeLimit**
147- Description: It affects the decision for performing full marking and concurrent marking.
148
149#### GC Triggered Upon Switching to Background
150
151- Functions: **ChangeGCParams**
152- Description: Full GC is triggered when the application switches to the background.
153- Log keywords: **app is inBackground**, **app is not inBackground**, and
154  **GCReason::SWITCH_BACKGROUND**
155
156### Execution Policy
157
158#### Concurrent Marking
159
160- Function: **TryTriggerConcurrentMarking**
161- Description: Attempts to trigger concurrent marking and hand over the object traversal task to the thread pool to reduce the time that the main thread is being suspended.
162- Log keywords: **fullMarkRequested, trigger full mark**, **Trigger the first full mark**, **Trigger full mark**, **Trigger the first semi mark**, and **Trigger semi mark**
163
164#### Threshold Adjustment Before and After GC of Semi Space
165
166- Function: **AdjustCapacity**
167- Description: Adjusts the GC trigger threshold of Semi Space after GC to optimize the space structure.
168- Log keywords: There is no direct log. The GC statistics logs show that the young space threshold before GC is dynamically adjusted.
169
170#### Threshold Adjustment After the First Old GC
171
172- Function: **AdjustOldSpaceLimit**
173- Description: Adjusts the old space threshold based on the minimum increase step and average survival rate.
174- Log keywords: **"AdjustOldSpaceLimit oldSpaceAllocLimit_: "<< oldSpaceAllocLimit <<" globalSpaceAllocLimit_: " << globalSpaceAllocLimit_;**
175
176#### Old Space/Global Space Threshold and Increase Factor for the Second and Later Old GC Operations
177
178- Function: **RecomputeLimits**
179- Description: Recalculates and adjusts **newOldSpaceLimit**, **newGlobalSpaceLimit**, **globalSpaceNativeLimit**, and the increase factor based on the current GC statistics.
180- Log keywords: **"RecomputeLimits oldSpaceAllocLimit_: "<< newOldSpaceLimit_ <<" globalSpaceAllocLimit_: "<< globalSpaceAllocLimit_ <<" globalSpaceNativeLimit_: "<< globalSpaceNativeLimit_;**
181
182#### CSet for Partial GC
183
184- Function: **OldSpace::SelectCSet ()**
185- Description: Selects a region with a small number of living objects and a low reclamation cost for partial GC.
186- Log keywords: **Select CSet failure: number is too few**,
187  **"Max evacuation size is 6_MB. The CSet region number: " << selectedRegionNumber;**,
188  and **"Select CSet success: number is " << collectRegionSet_.size();**
189
190## SharedHeap
191
192### Shared Heap Structure
193
194![image](./figures/gc-shared-heap.png)
195
196- Shared Old Space: stores common shared objects. The young generation and old generation are not distinguished in the shared heap.
197- Shared Huge Object Space: stores huge shared objects. A separate region is used to store a huge object.
198- Shared Read Only Space: stores read-only shared data at runtime.
199- Shared Non-Movable Space: stores unmovable shared objects.
200
201Note: The shared heap is mainly used to share objects between threads. It improves efficiency and reduces memory usage. The shared heap does not belong to a specific thread. It stores objects with shared value and has a higher survival rate. It does not evolve Semi Space.
202
203## Technical Features
204
205### Smart GC
206
207#### Description
208
209In performance-sensitive scenarios, the GC trigger threshold of the JS thread is temporarily adjusted to the maximum JS heap size (448 MB by default) to prevent frame loss caused by the GC trigger. (Smart GC does not take effect for the Worker thread and TaskPool thread.) However, if the performance-sensitive scenario lasts for a long period of time and the allocated objects reach the maximum heap size, GC is triggered. This GC takes a long time because too many objects are accumulated.
210
211#### Performance-Sensitive Scenarios
212
213- Application cold start
214- Application sliding
215- Page redirection upon click
216- Jumbo frame
217
218Application cold start is supported by default. In other scenarios, you can call the **dfxjsnapi** interface for configuration and there is no essential difference.
219
220Log keyword: **SmartGC**
221
222#### Interaction Process
223
224![image](./figures/gc-smart-feature.png)
225
226Mark performance-sensitive scenarios. When entering or exiting a performance-sensitive scenario, mark the scenario on the heap to avoid unnecessary GC and maintain high performance.
227
228### Idle GC
229
230The thread idle time in the system frame drawing process is used to efficiently utilize computing resources to complete GC by phase, reducing janky frames caused by subsequent long GC pauses triggered by accumulated memory usage.
231
232#### **Incremental Marking**
233
234It usually takes a long period of time (longer than one idle time period) to complete old GC. Therefore, the marking process is distributed in multiple idle time periods.
235
236![image](./figures/gc-incremental-mark-feature.png)
237
238Incremental marking is triggered during linear space expansion when the following conditions are met:
239
240- **ENABLE_IDLE_GC** is enabled in **ArkProperties** and the idleTime switch callback function sent by the ability is received.
241- There is no idle task and concurrent marking is not triggered.
242- When incremental marking is complete, the difference between the heap size and the threshold is less than 256 KB.
243- The size of the allocated object is less than 100 KB during incremental marking.
244
245Incremental marking and full concurrent marking are mutually exclusive. Linear space mainly refers to Semi Space.
246
247#### **Idle Young GC**
248
249![image](./figures/gc-idle-feature.png)
250
251During linear space expansion, the system attempts to trigger idle GC and set an idle task when the following conditions are met:
252
253- **ENABLE_IDLE_GC** is enabled in **ArkProperties** and the idleTime switch callback function sent by the ability is received.
254- There is no idle task and concurrent marking is not triggered.
255- The heap size is less than 256 KB or less than the young GC concurrent mark threshold.
256
257Idle young GC can coexist with concurrent marking to prevent the GC threshold from being reached before the idle time is received. Concurrent marking can be triggered before idle young GC starts.
258
259## Log Description
260
261### Typical Logs
262
263```
264// Actual size occupied by the object before GC (actual size occupied by the region) - > Actual size occupied by the object after GC (actual size occupied by the region), total duration (+concurrentMark duration), and GC triggering cause
265C03F00/ArkCompiler: [gc]  [ CompressGC ] 26.1164 (35) -> 7.10049 (10.5) MB, 160.626(+0)ms, Switch to background
266// GC statuses and application name
267C03F00/ArkCompiler: [gc] IsInBackground: 1; SensitiveStatus: 0; OnStartupEvent: 0; BundleName: com.huawei.hmos.filemanager;
268// Time consumption statistics of each GC phase
269C03F00/ArkCompiler: [gc] /***************** GC Duration statistic: ****************/
270C03F00/ArkCompiler: [gc] TotalGC:                 160.626 ms
271C03F00/ArkCompiler: Initialize:              0.179   ms
272C03F00/ArkCompiler: Mark:                    159.204 ms
273C03F00/ArkCompiler: MarkRoots:               6.925   ms
274C03F00/ArkCompiler: ProcessMarkStack:        158.99  ms
275C03F00/ArkCompiler: Sweep:                   0.957   ms
276C03F00/ArkCompiler: Finish:                  0.277   ms
277// Memory size occupied by each part after GC
278C03F00/ArkCompiler: [gc] /****************** GC Memory statistic: *****************/
279C03F00/ArkCompiler: [gc] AllSpaces        used:  7270.9KB     committed:   10752KB
280C03F00/ArkCompiler: ActiveSemiSpace  used:       0KB     committed:     256KB
281C03F00/ArkCompiler: OldSpace         used:  4966.9KB     committed:    5888KB
282C03F00/ArkCompiler: HugeObjectSpace  used:    2304KB     committed:    2304KB
283C03F00/ArkCompiler: NonMovableSpace  used:       0KB     committed:    2304KB
284C03F00/ArkCompiler: MachineCodeSpace used:       0KB     committed:       0KB
285C03F00/ArkCompiler: HugeMachineCodeSpace used:       0KB     committed:       0KB
286C03F00/ArkCompiler: SnapshotSpace    used:       0KB     committed:       0KB
287C03F00/ArkCompiler: AppSpawnSpace    used: 4736.34KB     committed:    4864KB
288C03F00/ArkCompiler: [gc] Anno memory usage size:  45      MB
289C03F00/ArkCompiler: Native memory usage size:2.99652 MB
290C03F00/ArkCompiler: NativeBindingSize:       0.577148KB
291C03F00/ArkCompiler: ArrayBufferNativeSize:   0.0117188KB
292C03F00/ArkCompiler: RegExpByteCodeNativeSize:0.280273KB
293C03F00/ArkCompiler: ChunkNativeSize:         19096   KB
294C03F00/ArkCompiler: [gc] Heap alive rate:         0.202871
295// Overall statistics of this type of GC on the VM
296C03F00/ArkCompiler: [gc] /***************** GC summary statistic: *****************/
297C03F00/ArkCompiler: [gc] CompressGC occurs count  6
298C03F00/ArkCompiler: CompressGC max pause:    2672.33 ms
299C03F00/ArkCompiler: CompressGC min pause:    160.626 ms
300C03F00/ArkCompiler: CompressGC average pause:1076.06 ms
301C03F00/ArkCompiler: Heap average alive rate: 0.635325
302```
303
304- GC type, which can be [HPP YoungGC], [HPP OldGC], [CompressGC] and [SharedGC].
305- **TotalGC**: total duration. The following lists the time required for each phase, including Initialize, Mark, MarkRoots, ProcessMarkStack, Sweep, and Finish. The actual phase varies according to the GC process.
306- **IsInBackground**: specifies whether it is a background scenario. The options are **1** (background scenario) and **0** (non-background scenario).
307- **SensitiveStatus**: specifies whether it is a sensitive scenario. The options are **1** (sensitive scenario) and **0** (non-sensitive scenario).
308- **OnStartupEvent**: specifies whether it is a cold start scenario. The options are **1** (cold start scenario) and **0** (non-cold start scenario).
309- **used**: actual memory space occupied by the allocated object.
310- **committed**: size of the memory allocated to the heap. Memory space is allocated by region, and a region is not fully occupied by objects. Therefore, if **committed** is greater than or equal to **used**, the values of **HugeObjectSpace** is the same under **used** and **committed** because one object occupies the region.
311- **Anno memory usage size**: memory size applied by all heaps of the current process, including the heap and shared heap.
312- **Native memory usage size**: native memory size requested by the current process.
313- **NativeBindingSize**: size of the native memory bound to the objects in the heap of the current process.
314- **ArrayBufferNativeSize**: native memory size of the array cache requested by the current process.
315- **RegExpByteCodeNativeSize**: native memory size of the regular expression bytecode requested by the current process.
316- **ChunkNativeSize**: chunk native memory size requested by the current process.
317- **Heap alive rate**: survival rate of objects in the heap.
318
319## GC Developer Debugging Interfaces
320
321> **NOTE**
322>
323> The following interfaces are used only for debugging. They are informal external SDK interfaces and should not be used in official application versions.
324
325### ArkTools.hintGC()
326
327- Call method: **ArkTools.hintGC()**
328- Type: JS interface
329- Description: Determines whether full GC is required. In the background scenario or if the expected survival rate is lower than the preset value, full GC is triggered. In performance-sensitive scenarios, full GC is not triggered.
330- Use scenario: The developer asks the system to perform GC.
331- Log keywords: There is no direct log. Only external trigger (**GCReason::TRIGGER_BY_JS**) can be found.
332
333
334Example:
335
336```
337// Declare the interface first.
338declare class ArkTools {
339     static hintGC(): void;
340}
341
342@Entry
343@Component
344struct Index {
345  @State message: string = 'Hello World';
346  build() {
347  Row() {
348    Column() {
349      Text(this.message)
350        .fontSize(50)
351        .fontWeight(FontWeight.Bold)
352      Button("Trigger Hint GC").onClick((event: ClickEvent) => {
353          ArkTools.hintGC(); // Directly called in a method.
354      })
355    }
356    .width('100%')
357  }
358  .height('100%')
359}
360}
361```
362