Golang效能最佳化實踐

王鹏鑫發表於2024-06-13

記憶體警察

警惕一切隱式記憶體分配

典型case:

  函式返回了字串、切片,警惕一切字串

傳進去的輸入,函式內部重新分配了一個新的記憶體返回

物件複用

1.sync.pool

保證有一個ch大小的物件可用

假設有cpu核數那麼多併發任務,可以保證gc的時候有保底在

2.區域性cache

sync.pool畢竟加鎖,要本地ctx能掛載臨時物件集,那肯定比pool效率高

currAccmulator在for迴圈之外的一個臨時變數

封裝在ctx裡面的一個臨時變數,跟隨ctx整個生命週期銷燬

storage儲存,後續還能複用

slice複用

1.len與cap

func TestD(t *testing.T) {
    ints := make([]int, 0, 6)
    ints = append(ints, 6, 6, 6, 6, 6, 6)
    // The clear built-in function clears maps and slices.
    // For maps, clear deletes all entries, resulting in an empty map.
    // For slices, clear sets all elements up to the length of the slice
    clear(ints)
    logger.DEBUG("ints", ints, " cap: ", cap(ints), " len:", len(ints))
    ints = ints[:0] // len == 0, cap == 6 之前的元素還在
    logger.DEBUG("ints", ints, " cap: ", cap(ints), " len:", len(ints))
    ints = append(ints[:0], 1, 2, 3) // 這樣就覆蓋了原來的元素
    logger.DEBUG("ints", ints, " cap: ", cap(ints), " len:", len(ints))

    // recap
    additionalItems := 10
    intsLen := len(ints)
    if n := intsLen + additionalItems - cap(ints); n > 0 {
        ints = append(ints[:cap(ints)], make([]int, n)...)
    }
    ints = ints[:intsLen]
    // resize
    size := 10
    if cap(ints) > size {
        ints = ints[:size]
    } else {
        ints = make([]int, size)
    }
}
=== RUN   TestD
2024/06/13 23:24:27 [DEBUG] ints[0 0 0 0 0 0] cap: 6 len:6 
2024/06/13 23:24:27 [DEBUG] ints[] cap: 6 len:0 

2024/06/13 23:24:27 [DEBUG] ints[1 2 3] cap: 6 len:3 

2.string與bytes

跨型別複用

1.unsafe

2.arena

生命週期管理

相關文章