You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: content/learning-paths/servers-and-cloud-computing/go-gc-default-settings/_index.md
+6-8Lines changed: 6 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,25 +1,22 @@
1
1
---
2
-
title: Measure Go GC behavior on AWS Graviton
3
-
draft: true
4
-
cascade:
5
-
draft: true
2
+
title: Measure and modify Go garbage collection behavior on AWS Graviton-based compute
6
3
7
-
description: Learn how to run Go benchmarks on AWS Graviton, capture GC metrics and pprof profiles, and establish a reproducible default-GC baseline for memory-intensive workloads on Arm.
4
+
description: Learn how to run Go benchmarks on AWS Graviton-based compute, capture GC metrics and pprof profiles with Benchstat, establish a reproducible default garbage collection baseline for memory-intensive workloads on Arm, and experiment with modifying garbage collection behavior.
8
5
9
6
minutes_to_complete: 75
10
7
11
8
who_is_this_for: This Learning Path is for engineers interested in learning more about Go garbage collection (GC) behavior on Arm.
12
9
13
10
learning_objectives:
14
-
- Select an AWS Graviton instance for repeatable Go GC measurements
11
+
- Select an AWS Graviton-based instance for repeatable Go GC measurements
15
12
- Install Go and Benchstat on an Arm Linux server
16
13
- Run a Go benchmark that reports allocation, GC, and pause-time metrics
17
14
- Capture CPU and heap profiles without changing GC behavior
15
+
- Interpret benchmarking results and experiment with changing GC behavior
18
16
19
17
prerequisites:
20
-
- An [AWS account](https://aws.amazon.com/) with permission to launch AWS GravitonEC2 instances
18
+
- An [AWS account](https://aws.amazon.com/) with permission to launch an AWS Graviton-based Amazon EC2 instance running Ubuntu 24.04 LTS or another Arm Linux distribution
21
19
- The [AWS CLI](/install-guides/aws-cli/) installed and configured on your local machine
22
-
- An AWS Graviton instance running Ubuntu 24.04 LTS or another Arm Linux distribution
23
20
- Basic familiarity with Go benchmarks and Linux shell commands
title: Choose an AWS Graviton-based instance for Go garbage collection benchmarking
3
+
description: Choose and launch an AWS Graviton-based Amazon EC2 instance for repeatable Go garbage collection benchmark measurements.
3
4
weight: 2
4
5
5
6
### FIXED, DO NOT MODIFY
6
7
layout: learningpathall
7
8
---
8
-
## What is Garbage Collection? (GC)
9
-
Memory management is a critical aspect of application performance, and Garbage Collection (GC) plays a central role in automating that process. GC continuously identifies and removes objects that are no longer needed, freeing memory for reuse.
9
+
## Understand Go garbage collection
10
10
11
-
While this automation improves productivity and application safety, inefficient garbage collection can lead to increased CPU usage, longer response times, and unexpected application pauses.
11
+
Memory management is a critical aspect of application performance. Garbage collection (GC) plays a important role in automating memory management. GC continuously identifies and removes objects that are no longer needed, freeing memory for reuse.
12
12
13
-
Tracking GC metrics provides a window into an application's memory health, helping engineers optimize performance, and ensuring the system can scale efficiently under load.
13
+
This automation improves productivity and application safety. However, inefficient GC can lead to increased CPU usage, longer response times, and unexpected application pauses.
14
14
15
-
## Measuring default Go GC behavior on Arm servers
15
+
Tracking GC metrics provides a window into an application's memory health that you can use to optimize performance and ensure the system can scale efficiently under load.
16
16
17
-
Go is one such language that implements GC. As Go applications can spend meaningful time allocating memory and running garbage collection, it is important to understand how the Go runtime behaves under default settings.
17
+
Go applications can spend meaningful time allocating memory and running GC. This makes it important to understand how the Go runtime behaves under default settings.
18
18
19
-
In this Learning Path, you'll run Go benchmarks on an AWS Graviton instance. The goal is to build a clean baseline, measuring operation time, allocation rate, GC frequency, and GC pause cost.
19
+
In this Learning Path, you'll run Go benchmarks on an Amazon EC2 instance powered by AWS Graviton. The goal is to build a clean baseline measuring operation time, allocation rate, GC frequency, and GC pause cost.
20
20
21
-
## Selecting an instance for Go GC measurements
21
+
## Select an instance for Go garbage collection measurements
22
22
23
-
An AWS Graviton `m8g.xlarge` instance has enough CPU and memory to make Go runtime behavior visible, while keeping costs minimal. It's a good starting point as it provides four vCPUs and 16 GiB of memory on AWS Graviton4. If you choose to run this Learning Path on a different instance, make sure it has at least 4 vCPUs and 16 GiB of memory to ensure the benchmark runs smoothly and provides meaningful GC metrics.
24
-
25
-
Avoid burstable `t4g` instances as CPU credits can affect benchmark repeatability and make GC measurements harder to explain.
23
+
An `m8g.xlarge` instance powered by AWS Graviton has enough CPU and memory to make Go runtime behavior visible, while keeping costs minimal. It's a good starting point because it provides four vCPUs and 16 GiB of memory on AWS Graviton4.
26
24
27
25
{{% notice Note %}}
28
-
You can use larger instances, such as `m8g.2xlarge`, when you want more CPU width or more memory headroom. Start with `m8g.xlarge` so the first benchmark run is easy to reproduce and inexpensive.
29
-
{{% /notice %}}
26
+
You can use larger instances, such as `m8g.2xlarge`, when you want more CPU capacity or memory. Start with `m8g.xlarge` so the first benchmark run is easy to reproduce and inexpensive.
30
27
28
+
If you choose to run this Learning Path on a different instance, make sure it has at least four vCPUs and 16 GiB of memory to ensure the benchmark runs smoothly and provides meaningful GC metrics.
31
29
32
-
## Checking instance availability
30
+
Avoid burstable `t4g` instances as CPU credits can affect benchmark repeatability and make GC measurements harder to explain.
31
+
{{% /notice %}}
33
32
34
-
Use the AWS CLI to check whether `m8g.xlarge` is available in your selected Region.
35
33
36
-
Replace `us-east-1` with the Region you want to use.
34
+
### Check instance availability
35
+
36
+
Use the AWS CLI to check whether `m8g.xlarge` is available in your selected AWS Region, replacing `us-east-1` with the Region you want to use:
If the command returns one or more Availability Zones, you can use `m8g.xlarge` in that Region. If `m8g.xlarge` is not available in your Region, try a different Region, or fall back to an `m7g.xlarge` instance, which is based on the previous generation AWS Graviton3:
47
+
If the command returns one or more Availability Zones, you can use `m8g.xlarge` in that Region.
48
+
49
+
If `m8g.xlarge` is not available in your Region, try a different Region, or fall back to an `m7g.xlarge` instance, which is based on the previous generation AWS Graviton3:
After selecting an instance type, launch it with the Ubuntu 24.04 LTS (arm64) AMI. You can do this through the [AWS EC2 console](https://console.aws.amazon.com/ec2/) or the AWS CLI. When configuring the instance:
60
+
### Launch an instance
61
+
62
+
After selecting an instance type, launch it with the Ubuntu 24.04 LTS (arm64) AMI. You can do this using the [Amazon EC2 console](https://console.aws.amazon.com/ec2/) or the AWS CLI. When configuring the instance:
59
63
60
64
- Select your chosen instance type (`m8g.xlarge` or `m7g.xlarge`)
61
65
- Choose the Ubuntu 24.04 LTS arm64 AMI for your Region
@@ -67,5 +71,8 @@ After the instance reaches the running state, connect to it over SSH:
You now know why measuring Go GC behavior is useful, and you've deployed an Arm-based Amazon EC2 instance powered by AWS Graviton.
70
77
71
-
You now have a running Arm Linux instance on AWS Graviton. In the next section you'll install Go and Benchstat so the instance is ready to run benchmarks.
78
+
Next, you'll install Go and Benchstat on the instance so that you can run GC benchmarks.
// Next, we tell the benchmark framework to track memory allocations.
60
+
// Tells the benchmark framework to track memory allocations.
59
61
//
60
62
// This will show metrics such as allocations per operation, and bytes allocated per operation
61
63
62
64
b.ReportAllocs()
63
65
64
-
// Capture runtime memory statistics before the benchmark starts. We will later compare these
65
-
// values to see:
66
-
// - how many garbage collections occurred
67
-
// - how much pause time was spent in GC
66
+
/*
67
+
Captures runtime memory statistics before the benchmark starts. You'll later compare these values to see:
68
+
- how many GCs occurred
69
+
- how much pause time was spent in GC
70
+
*/
68
71
69
72
var before runtime.MemStats
70
73
runtime.ReadMemStats(&before)
71
74
72
-
// Reset benchmark timing so that any setup work performed above will not be included
73
-
// in the benchmark measurements.
75
+
// Resets benchmark timing so that any setup work performed won't be included in the benchmark measurements.
74
76
75
77
b.ResetTimer()
76
78
77
-
// The benchmark loop is where the actual work is done. The number of times this loop is
78
-
// executed is controlled by the b.N variable. The value of b.N is automatically chosen by
79
-
// the Go benchmark framework to obtain stable and statistically useful measurements.
80
-
81
-
// The reason for this design is that timing a single operation is often unreliable; running
82
-
// it many times reduces noise from:
83
-
// * OS scheduling
84
-
// * CPU frequency changes
85
-
// * background processes
79
+
/*
80
+
Benchmark loop where the actual work is done. The number of times this loop is
81
+
executed is controlled by the b.N variable. The value of b.N is automatically chosen by the Go benchmark framework to obtain stable and statistically useful measurements.
82
+
83
+
The reason for this design is that timing a single operation is often unreliable. Running it many times reduces noise from:
84
+
- OS scheduling
85
+
- CPU frequency changes
86
+
- background processes
87
+
*/
86
88
87
89
for i := 0; i < b.N; i++ {
88
-
// split the large payload into individual records.
// Create a new slice to store parsed output. This allocation is intentional because we want
93
-
// the benchmark to generate memory pressure and trigger garbage collection activity.
93
+
// Creates a new slice to store parsed output. This allocation is intentional for the benchmark to generate memory pressure and trigger GC activity.
94
94
95
95
out := make([]string, 0, len(parts))
96
96
97
-
// Process each record.
97
+
// Processes each record.
98
98
99
99
for _, part := range parts {
100
-
// Ignore the empty string created by the trailing semicolon.
100
+
// Ignores the empty string created by the trailing semicolon.
101
101
if part == "" {
102
102
continue
103
103
}
104
-
// Split the string into key and value.
104
+
// Splits the string into key and value.
105
105
106
106
fields := strings.SplitN(part, "=", 2)
107
107
108
-
// Make sure both key and value exist.
108
+
// Makes sure both key and value exist.
109
109
if len(fields) == 2 {
110
-
// Build a new string containing: key:length_of_value
111
-
// This creates additional allocations and string objects, increasing GC activity.
110
+
// Builds a new string containing: key:length_of_value. This creates additional allocations and string objects, increasing GC activity.
112
111
out = append(out,fields[0]+":"+strconv.Itoa(len(fields[1])),)
113
112
}
114
113
}
115
-
// Save the result so the compiler cannot eliminate the work as unused.
114
+
// Saves the result so the compiler can't eliminate the work as unused.
116
115
sink = out
117
116
}
118
-
// Stop benchmark timing.
119
-
//
120
-
// Everything below is measurement/reporting logic and should not affect benchmark performance results.
117
+
// Stops benchmark timing.
118
+
// Everything that follows is measurement or reporting logic and shouldn't affect benchmark performance results.
121
119
b.StopTimer()
122
120
123
-
// Capture memory statistics after the benchmark completes.
121
+
// Captures memory statistics after the benchmark completes.
124
122
125
123
var after runtime.MemStats
126
124
runtime.ReadMemStats(&after)
127
125
128
126
// Number of benchmark operations executed.
129
127
ops := float64(b.N)
130
128
131
-
// Total number of garbage collection cycles that occurred while the benchmark was running:
129
+
// Total number of GC cycles that occurred while the benchmark was running:
132
130
133
131
gcCycles := after.NumGC - before.NumGC
134
132
135
-
// Total "stop-the-world" pause time spent in GC. During these pauses, application execution
136
-
// is temporarily halted while the runtime performs parts of garbage collection.
133
+
/*
134
+
Total "stop-the-world" pause time spent in GC. During these pauses, application execution is temporarily halted while the runtime performs parts of GC.
The benchmark code is now ready. Run the following command to verify it executes without errors:
159
+
The benchmark code is now ready.
160
+
161
+
Run the following command to verify it executes without errors:
162
162
163
163
```bash
164
164
cd$HOME/go-gc-default
165
165
go test ./parsebench -run '^$' -bench BenchmarkParseAndAllocate -benchmem -count 1 -benchtime=2s
166
166
```
167
167
168
-
You should see output similar to below:
168
+
The output is similar to:
169
169
170
170
```output
171
171
goos: linux
@@ -176,7 +176,10 @@ PASS
176
176
ok example.com/go-gc-default/parsebench 4.127s
177
177
```
178
178
179
-
Your exact numbers will differ by instance type, Go version, operating system, and system load. If this test run yields results with no errors, you're ready to move on to the next step.
179
+
Your exact numbers will differ by instance type, Go version, operating system, and system load. If this test run yields results with no errors, you're ready to move to the next section.
180
180
181
+
## What you've accomplished and what's next
181
182
183
+
You've now created a Go GC benchmark module.
182
184
185
+
Next, you'll run the benchmark with default GC settings.
0 commit comments