我有一個加載幾個千兆位元組的位元組陣列的應用程式。我無法控制二進制格式。該程式花費大部分時間將陣列的各個部分轉換為字串,進行字串操作,然后釋放所有字串。當有大量客戶端觸發在記憶體中分配的大量物件時,它偶爾會耗盡記憶體。
鑒于位元組陣列在應用程式的整個生命周期中都存在于記憶體中,它似乎是使用 unsafe 包來避免記憶體分配的理想候選者。
只是在 go 操場上測驗一下,似乎需要一個“SliceHeader”來生成一個實際的字串。但這意味著每次需要回傳字串時仍必須分配“SliceHeader”。(即本例中的“x”變數)
func main() {
t := []byte{
65, 66, 67, 68, 69, 70,
71, 72, 73, 74, 75, 76,
77, 78, 79, 80, 81, 82,
83, 84, 85,
}
var x [10]reflect.StringHeader
h := (*reflect.StringHeader)(unsafe.Pointer(&x[0]))
h.Len = 4
h.Data = uintptr(unsafe.Pointer(&t[8]))
fmt.Printf("test %v\n", *(*string)(unsafe.Pointer(&x[0])))
h = (*reflect.StringHeader)(unsafe.Pointer(&x[1]))
h.Len = 4
h.Data = uintptr(unsafe.Pointer(&t[3]))
fmt.Printf("test %v\n", *(*string)(unsafe.Pointer(&x[1])))
}
當每個客戶端連接到服務器時(在新客戶端連接時重新回圈),我可能會為每個客戶端附加一個具有固定長度的字串頭物件集的陣列。
這意味著 1. 字串資料將不再被復制,并且 2. 字串標頭不會被分配/垃圾收集。3. 我們知道每臺服務器的最大客戶端數量,因為它們在提取字串時具有固定/硬編碼數量的可用字串頭。
我走上正軌了嗎,瘋了嗎?讓我知道??謝謝。
uj5u.com熱心網友回復:
使用以下函式將位元組切片轉換為字串而不進行分配:
func btos(p []byte) string {
return *(*string)(unsafe.Pointer(&p))
}
該函式利用了字串頭的記憶體布局是切片頭的記憶體布局的前綴這一事實。
呼叫此函式后不要修改切片的后備陣列——這將打破字串不可變的假設。
像這樣使用函式:
t := []byte{
65, 66, 67, 68, 69, 70,
71, 72, 73, 74, 75, 76,
77, 78, 79, 80, 81, 82,
83, 84, 85,
}
s := btos(t[8:12])
fmt.Printf("test %v\n", s) // prints test IJKL
s = btos(t[3:7])
fmt.Printf("test %v\n", s) // prints test DEFG
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/417953.html
標籤:
上一篇:試圖從JSON小節中獲取2個整數
