74 lines
1.9 KiB
Go
74 lines
1.9 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"runtime"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// 初始化1KB字节切片对象池
|
|
var bytePool = sync.Pool{
|
|
New: func() interface{} {
|
|
return make([]byte, 1024)
|
|
},
|
|
}
|
|
|
|
// 打印GC统计,衔接你之前的知识
|
|
func printGCStatsInfo(title string) {
|
|
var stats runtime.MemStats
|
|
runtime.ReadMemStats(&stats)
|
|
fmt.Printf("[%s] GC次数: %d, 存活堆内存: %d KB\n", title, stats.NumGC, stats.HeapAlloc/1024)
|
|
}
|
|
|
|
// withoutPool 不使用对象池,频繁分配新内存
|
|
// 增加参数 []byte 模拟真实业务使用,禁止编译器消除代码
|
|
func withoutPool() time.Duration {
|
|
start := time.Now()
|
|
var temp []byte // 用于承接数据,避免死代码
|
|
for i := 0; i < 1000000; i++ { // 循环次数提升10倍,让耗时可被精准统计
|
|
buf := make([]byte, 1024)
|
|
temp = append(temp, buf...) // 模拟真实使用切片,编译器无法优化
|
|
}
|
|
_ = temp
|
|
return time.Since(start)
|
|
}
|
|
|
|
// withPool 使用对象池复用内存
|
|
func withPool() time.Duration {
|
|
start := time.Now()
|
|
var temp []byte // 用于承接数据,避免死代码
|
|
for i := 0; i < 1000000; i++ { // 同步提升循环次数
|
|
buf := bytePool.Get().([]byte)
|
|
temp = append(temp, buf...) // 模拟真实使用切片
|
|
bytePool.Put(buf[:0]) // 正确放回,保留你的最佳实践
|
|
}
|
|
_ = temp
|
|
return time.Since(start)
|
|
}
|
|
|
|
func main() {
|
|
// 预热并清空GC状态
|
|
runtime.GC()
|
|
printGCStatsInfo("初始化")
|
|
|
|
// 测试无对象池
|
|
dur1 := withoutPool()
|
|
printGCStatsInfo("无对象池后")
|
|
runtime.GC() // 强制GC,消除前序影响
|
|
|
|
// 测试有对象池
|
|
dur2 := withPool()
|
|
printGCStatsInfo("有对象池后")
|
|
|
|
// 增加分母非0判断,避免-Inf%
|
|
var rate float64
|
|
if dur1 > 0 {
|
|
rate = (1 - float64(dur2)/float64(dur1)) * 100
|
|
}
|
|
|
|
fmt.Printf("\n无对象池耗时: %v\n", dur1)
|
|
fmt.Printf("有对象池耗时: %v\n", dur2)
|
|
fmt.Printf("性能提升: %.2f%%\n", rate)
|
|
}
|