在Go里,垃圾收集器并不是完全"stop-the-world",而是与应用程序并行执行其大部分工作(例如标记堆) 。
但是 , 垃圾收集器的操作仍然有一些限制,并且会在一个周期内多次完全停止工作代码的执行,想要了解更多可以阅读源码[5] 。
如何管理垃圾收集器在Go中可以通过某些参数管理垃圾收集器: GOGC环境变量或runtime/debug包中的等效函数SetGCPercent 。
GOGC参数确定将触发垃圾收集的新未分配堆内存相对于活跃内存的百分比 。
GOGC的默认值是100 , 意味着当新内存达到活跃堆内存的100%时将触发垃圾收集 。
文章插图
当新堆占用活跃堆的100%时,将运行垃圾收集器
我们以示例程序为例,通过go tool trace跟踪堆大小的变化,我们用Go 1.20.1版本来运行程序 。
在本例中,performMemoryIntensiveTask函数使用了在堆中分配的大量内存 。这个函数启动一个队列大小为NumWorker的工作池 , 任务数量等于NumTasks 。
package mainimport ( "fmt" "os" "runtime/debug" "runtime/trace" "sync")const ( NumWorkers= 4// Number of workers. NumTasks= 500// Number of tasks. MemoryIntense = 10000 // Size of memory-intensive task (number of elements).)func main() { // Write to the trace file. f, _ := os.Create("trace.out") trace.Start(f) defer trace.Stop() // Set the target percentage for the garbage collector. Default is 100%. debug.SetGCPercent(100) // Task queue and result queue. taskQueue := make(chan int, NumTasks) resultQueue := make(chan int, NumTasks) // Start workers. var wg sync.WaitGroup wg.Add(NumWorkers) for i := 0; i < NumWorkers; i++ {go worker(taskQueue, resultQueue, &wg) } // Send tasks to the queue. for i := 0; i < NumTasks; i++ {taskQueue <- i } close(taskQueue) // Retrieve results from the queue. go func() {wg.Wait()close(resultQueue) }() // Process the results. for result := range resultQueue {fmt.Println("Result:", result) } fmt.Println("Done!")}// Worker function.func worker(tasks <-chan int, results chan<- int, wg *sync.WaitGroup) { defer wg.Done() for task := range tasks {result := performMemoryIntensiveTask(task)results <- result }}// performMemoryIntensiveTask is a memory-intensive function.func performMemoryIntensiveTask(task int) int { // Create a large-sized slice. data := make([]int, MemoryIntense) for i := 0; i < MemoryIntense; i++ {data[i] = i + task } // Latency imitation. time.Sleep(10 * time.Millisecond) // Calculate the result. result := 0 for _, value := range data {result += value } return result}
跟踪程序执行的结果被写入文件trace.out:// Writing to the trace file.f, _ := os.Create("trace.out")trace.Start(f)defer trace.Stop()
通过go tool trace,可以观察堆大小的变化,并分析程序中垃圾收集器的行为 。请注意 , go tool trace的精确细节和功能可能因go版本不同而有所差异 , 因此建议参考官方文档 , 以获取有关其在特定go版本中使用的详细信息 。
GOGC的默认值GOGC参数可以使用runtime/debug包中的debug.SetGCPercent进行设置,GOGC默认设置为100% 。
用下面命令运行程序:
go run main.go
程序执行后,将会创建trace.out文件,可以使用go tool工具对其进行分析 。要做到这一点,执行命令:go tool trace trace.out
然后可以通过打开web浏览器并访问http://127.0.0.1:54784/trace来查看基于web的跟踪查看器 。文章插图
GOGC = 100
在"STATS"选项卡中 , 可以看到"Heap"字段,显示了在应用程序执行期间堆大小的变化情况,图中红色区域表示堆占用的内存 。
在"PROCS"选项卡中,"GC"(垃圾收集器)字段显示的蓝色列表示触发垃圾收集器的时刻 。
一旦新堆的大小达到活动堆大小的100% , 就会触发垃圾收集 。例如,如果活跃堆大小为10 MB , 则当当前堆大小达到10 MB时将触发垃圾收集 。
跟踪所有垃圾收集调用使我们能够确定垃圾收集器处于活动状态的总时间 。
文章插图
GOGC=100时的GC调用次数
示例中 , 当GOGC值为100时,将调用垃圾收集器16次,总执行时间为14 ms 。
更频繁的调用GC如果我们将debug.SetGCPercent(10)设置为10%后运行代码,将观察到垃圾收集器调用的频率更高 。现在,如果当前堆大小达到活跃堆大小的10%时,将触发垃圾收集 。
推荐阅读
- 微软 Edge 浏览器支持双引擎同时搜索功能,便利与槽点并存
- C++质数检测器的设计与实现?
- 羽毛球的起源与世界赛事的发展
- 再夺视帝的陈豪与陈茵媺在内地恩爱逛街 遇见粉丝一一开心合影
- 人民的名义:梁家势力不再,为何祁同伟还是不敢与梁璐彻底切割?
- 一个想上位、一个想白嫖,于正与祝绪丹的瓜,揭开娱乐圈的遮羞布
- 张兰看清现状主动放手,允许肖肖离职,与大S回归平静生活有关
- 29岁小杨哥现身香港谈合作!与周星驰一起喝早茶,搭肩合影受重视
- 她曾是“内地第一美女”,与丈夫恩爱37年,如今70岁仍气质迷人
- 端午节系红绳的寓意 端午节系红绳的寓意与作用