 闽公网安备 35020302035485号
                
                闽公网安备 35020302035485号
                import (
    "log"
    "net/http"
    _ "net/http/pprof" // Critical: anonymous import to register pprof handlers
)
func main() {
    // ... your application logic ...
    go func() {
        // Start the pprof server in a separate goroutine
        // It's generally not recommended to expose this to the public internet in production
        log.Println(http.ListenAndServe("localhost:6060", nil))
    }()
    // ...
}
一旦服务运行,使用  go tool pprof  命令来收集和分析数据。例如,收集 30 秒的 CPU 调试信息:// 堆代码 duidaima.com
// in string_concat_test.go
package main
import (
    "strings"
    "testing"
)
var testData = []string{"a", "b", "c", "d", "e", "f", "g"}
func BenchmarkStringPlus(b *testing.B) {
    b.ReportAllocs() // Reports memory allocations per operation
    for i := 0; i < b.N; i++ {
        var result string
        for _, s := range testData {
            result += s
        }
    }
}
func BenchmarkStringBuilder(b *testing.B) {
    b.ReportAllocs()
    for i := 0; i < b.N; i++ {
        var builder strings.Builder
        for _, s := range testData {
            builder.WriteString(s)
        }
        _ = builder.String()
    }
}
数据表明: strings.Builder  在性能和内存效率上都具有压倒性的优势。const count = 10000
// Bad practice: append() will trigger multiple reallocations
s := make([]int, 0)
for i := 0; i < count; i++ {
    s = append(s, i)
}
// Recommended practice: Allocate enough capacity at once
s := make([]int, 0, count)
for i := 0; i < count; i++ {
    s = append(s, i)
}
// The same logic applies to maps
m := make(map[int]string, count)
4. 使用  sync.Pool  重用频繁分配的对象import (
    "bytes"
    "sync"
)
var bufferPool = sync.Pool{
    New: func() interface{} {
        return new(bytes.Buffer)
    },
}
func ProcessRequest(data []byte) {
    buffer := bufferPool.Get().(*bytes.Buffer)
    defer bufferPool.Put(buffer) // defer ensures the object is always returned
    buffer.Reset()               // Reset the object's state before reuse
    // ... use the buffer ...
    buffer.Write(data)
}
注意: sync.Pool  中的对象可以在任何时间不通知地被垃圾回收。它仅适用于存储无状态的、临时的对象,这些对象可以按需重新创建。// Potential memory leak
func getSubSlice(data []byte) []byte {
    // The returned slice still references the entire underlying array of data
    return data[:10]
}
// The correct approach
func getSubSliceCorrectly(data []byte) []byte {
    sub := data[:10]
    result := make([]byte, 10)
    copy(result, sub) // Copy the data to new memory
    // result no longer has any association with the original data
    return result
}
经验法则:当你从一个大对象中提取一个小部分并且需要长期持有时,请进行复制。type BigStruct struct {
    data [1024 * 10]byte // A 10KB struct
}
// Inefficient: copies 10KB of data
func ProcessByValue(s BigStruct) { /* ... */ }
// Efficient: copies an 8-byte pointer
func ProcessByPointer(s *BigStruct) { /* ... */ }
另一方面:对于非常小的结构体(例如,仅包含几个  int ),通过值传递可能会更快,因为它避免了指针间接的开销。最终的裁决应来自基准测试。// Blocking model: A worker must be free for a task to be sent jobs := make(chan int) // Decoupled model: Tasks can sit in the buffer, waiting for a worker jobs := make(chan int, 100)10. sync.WaitGroup : 高并发环境下等待一组 goroutine 的标准方法
import "sync"
func main() {
    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            // ... perform task ...
        }()
    }
    wg.Wait() // Wait for all the goroutines above to complete
}
11. 在高并发环境下减少锁竞争分片:将一个大映射拆分成几个较小的映射,每个映射由自己的锁保护,以分散争用。
	
func worker(jobs <-chan int, results chan<- int) {
    for j := range jobs {
        // ... process job j ...
        results <- j * 2
    }
}
func main() {
    jobs := make(chan int, 100)
    results := make(chan int, 100)
    // Start 5 workers
    for w := 1; w <= 5; w++ {
        go worker(jobs, results)
    }
    // ... send tasks to the jobs channel ...
    close(jobs)
    // ... collect results from the results channel ...
}
第四部分:数据结构和算法中的微优化// More memory efficient
set := make(map[string]struct{})
set["apple"] = struct{}{}
set["banana"] = struct{}{}
// Check for existence
if _, ok := set["apple"]; ok {
    // exists
}
14. 避免热点循环中的不必要的计算items := []string{"a", "b", "c"}
// Bad practice: len(items) is called in every iteration
for i := 0; i < len(items); i++ { /* ... */ }
// Recommended practice: Pre-calculate the length
length := len(items)
for i := 0; i < length; i++ { /* ... */ }
15. 理解接口的运行时开销func getInt() *int {
    i := 10
    return &i // &i "escapes to heap"
}
查看  escapes to heap  输出可以告诉你堆分配的确切位置。如果必须使用 cgo ,请尽量减少调用次数。批量数据并进行一次调用远比在循环中反复调用 C 函数要好。
	
go build -pgo=cpu.pprof -o myapp_pgo myapp.go20. 保持 Go 版本更新