亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如果我知道許多 tmp 切片的最大大小,我應該在創建它們時設置容量嗎?

如果我知道許多 tmp 切片的最大大小,我應該在創建它們時設置容量嗎?

Go
搖曳的薔薇 2023-06-12 15:49:36
如果我需要在一個函數中使用 tmp 切片,并且該函數會被多次調用,它們的最大容量不會超過 10。但是它們的長度是多種多樣的。舉個例子,可能其中 80% 的尺寸只有 1。10% 的尺寸為 3,10% 的尺寸為 10。我可以想到如下示例函數:func getDataFromDb(s []string) []string {    tmpSlice := make([]string, 0, 10)    for _, v := range s {        if check(v) {            tmpSlice = append(tmpSlice, v)        }    }    ......    return searchDb(tmpSlice)}那么我應該做var tmpSlice []string, tmpSlice := make([]string, 0, 0), tmpSlice := make([]string, 0, 5), 還是tmpSlice := make([]string, 0, 10)?或任何其他建議?
查看完整描述

3 回答

?
慕絲7291255

TA貢獻1859條經驗 獲得超6個贊

最快的是代碼不在堆上分配。


創建在堆棧上分配且不轉義的變量(按值傳遞變量,否則它們將轉義)。


-gcflags "-m -l"逃避你可以通過添加建筑物來檢查。


這是一個示例,顯示如果我們slice用數組替換并按值傳遞它,它會產生快速代碼而無需分配(在堆上)。


package main


import "testing"


func BenchmarkAllocation(b *testing.B) {

    b.Run("Slice", func(b2 *testing.B) {

        for i := 0; i < b2.N; i++ {

            _ = getDataFromDbSlice([]string{"one", "two"})

        }

    })

    b.Run("Array", func(b2 *testing.B) {

        for i := 0; i < b2.N; i++ {

            _ = getDataFromDbArray([]string{"one", "two"})

        }

    })

}


type DbQuery [10]string

type DbQueryResult [10]string


func getDataFromDbArray(s []string) DbQueryResult {

    q := DbQuery{}

    return processQueryArray(q)

}


func processQueryArray(q DbQuery) DbQueryResult {

    return (DbQueryResult)(q)

}


func getDataFromDbSlice(s []string) []string {

    tmpArray := make([]string, 0, 10)

    return processQuerySlice(tmpArray)

}


func processQuerySlice(q []string) []string {

    return q

}

運行基準測試benchmem給出了以下結果:


BenchmarkAllocation/Slice-6             30000000            51.8 ns/op       160 B/op          1 allocs/op

BenchmarkAllocation/Array-6             100000000           15.7 ns/op         0 B/op          0 allocs/op



查看完整回答
反對 回復 2023-06-12
?
收到一只叮咚

TA貢獻1821條經驗 獲得超5個贊

    該答案假定searchDB不保留對傳遞給它的切片的引用。給定變量和函數名稱,函數似乎不太可能保留引用。


這些選項具有相同的內存和性能特征:


 var tmpSlice []string

 tmpSlice := []string{}

 tmpSlice := make([]string, 0)

 tmpSlice := make([]string, 0, 0)

在第一個追加操作之前,它們都不會分配內存。如果這些是您唯一的選擇,那么請選擇前兩個中的一個,因為它們更容易閱讀。


此選項將具有最佳性能:


tmpSlice := make([]string, 0, 10)

這確保了切片的后備數組被分配一次。附加值時不會重新分配支持數組。


如果searchDB的參數沒有逃逸,那么將在堆棧上為后備數組分配一次。這是最好的表現。您可以通過使用選項構建來確定參數是否逃逸-gcflags "-m -l"。


鑒于getDataFromDb調用數據庫操作,選項之間的任何性能差異都將被忽略。編寫清晰簡單的代碼比優化它更重要。


我可能會選擇var tmpSlice []stringover tmpSlice := make([]string, 0, 10),因為沒有必要了解前者的值 10 從何而來。


查看完整回答
反對 回復 2023-06-12
?
MM們

TA貢獻1886條經驗 獲得超2個贊

我會做

var tmpSlice []string

這會給你一個空字符串切片,你可以根據需要追加。除非切片范圍變大并且您事先知道維度,否則我不會為它預分配內存


查看完整回答
反對 回復 2023-06-12
  • 3 回答
  • 0 關注
  • 184 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號