go內存隊列l(wèi)ist VS slice實現(xiàn)方式對比分析
go隊列的實現(xiàn)方式
golang中沒有隊列這種數(shù)據(jù)結構,通常需要自己實現(xiàn),常見的可以通過list或slice實現(xiàn)。
list是"container/list"中的數(shù)據(jù)結構,用雙向鏈表實現(xiàn),可以用來做隊列:
//入隊
func (l *List) PushBack(v interface{}) *Element
//出隊:先Front()取得頭,然后Remove()刪除
func (l *List) Front() *Element
func (l *List) Remove(e *Element) interface{}slice實現(xiàn)隊列的方式:
var s []obj s = append(s, obj) //入隊 s = s[1:] //出隊
benchmark測試比較
benchmark測試代碼: 隊列中存入object對象
type EventMsg struct {
Id string
Msg string
}
func BenchmarkQueue_ListObject(b *testing.B) {
var l = list.New()
for i := 0; i < b.N; i++ {
l.PushBack(EventMsg{
Id: strconv.Itoa(i),
Msg: "1:abcdefghijklmnopqrstuvwxyz-abcdefghijklmnopqrstuvwxyz-abcdefghijklmnopqrstuvwxyz-abcdefghijklmnopqrstuvwxyz",
})
l.PushBack(EventMsg{
Id: strconv.Itoa(i),
Msg: "1:opqrstuvwxyzabcdefghijklmn-opqrstuvwxyzabcdefghijklmn-opqrstuvwxyzabcdefghijklmn-opqrstuvwxyzabcdefghijklmn",
})
l.Remove(l.Front())
}
}
func BenchmarkQueue_SliceObject(b *testing.B) {
var q []EventMsg
for i := 0; i < b.N; i++ {
q = append(q, EventMsg{
Id: strconv.Itoa(i),
Msg: "1:abcdefghijklmnopqrstuvwxyz-abcdefghijklmnopqrstuvwxyz-abcdefghijklmnopqrstuvwxyz-abcdefghijklmnopqrstuvwxyz",
})
q = append(q, EventMsg{
Id: strconv.Itoa(i),
Msg: "1:opqrstuvwxyzabcdefghijklmn-opqrstuvwxyzabcdefghijklmn-opqrstuvwxyzabcdefghijklmn-opqrstuvwxyzabcdefghijklmn",
})
q = q[1:]
}
}benchmark測試代碼:隊列中存入Object指針對象
func BenchmarkQueue_ListObjPtr(b *testing.B) {
var l = list.New()
for i := 0; i < b.N; i++ {
l.PushBack(&EventMsg{
Id: strconv.Itoa(i),
Msg: "1:abcdefghijklmnopqrstuvwxyz-abcdefghijklmnopqrstuvwxyz-abcdefghijklmnopqrstuvwxyz-abcdefghijklmnopqrstuvwxyz",
})
l.PushBack(&EventMsg{
Id: strconv.Itoa(i),
Msg: "1:opqrstuvwxyzabcdefghijklmn-opqrstuvwxyzabcdefghijklmn-opqrstuvwxyzabcdefghijklmn-opqrstuvwxyzabcdefghijklmn",
})
l.Remove(l.Front())
}
}
func BenchmarkQueue_SliceObjPtr(b *testing.B) {
var q []*EventMsg
for i := 0; i < b.N; i++ {
q = append(q, &EventMsg{
Id: strconv.Itoa(i),
Msg: "1:abcdefghijklmnopqrstuvwxyz-abcdefghijklmnopqrstuvwxyz-abcdefghijklmnopqrstuvwxyz-abcdefghijklmnopqrstuvwxyz",
})
q = append(q, &EventMsg{
Id: strconv.Itoa(i),
Msg: "1:opqrstuvwxyzabcdefghijklmn-opqrstuvwxyzabcdefghijklmn-opqrstuvwxyzabcdefghijklmn-opqrstuvwxyzabcdefghijklmn",
})
q = q[1:]
}
}benchmark測試結果
# go test -bench=BenchmarkQueue -count=1 -benchmem -cpu 4
BenchmarkQueue_ListObject-4 1000000 1423 ns/op 175 B/op 5 allocs/op
BenchmarkQueue_ListObjPtr-4 1000000 1124 ns/op 175 B/op 5 allocs/op
BenchmarkQueue_SliceObject-4 1000000 1574 ns/op 357 B/op 1 allocs/op
BenchmarkQueue_SliceObjPtr-4 1831449 662.7 ns/op 161 B/op 3 allocs/op
PASS
ok github.com/go_list/bench_test 6.144s
結論:
- 不管用list還是slice,隊列中存儲對象指針的性能,要好于直接存儲對象;
- slice實現(xiàn)的隊列,存儲指針對象時性能最好;
- list實現(xiàn)的隊列,不管是存儲對象還是指針對象,其性能差異不是太大;
Open-falcon的隊列實現(xiàn)
open-falcon使用list和mutex實現(xiàn)了一個協(xié)程安全的內存隊列。
實現(xiàn)代碼:https://github.com/toolkits/c...
type SafeList struct {
sync.RWMutex
L *list.List
}
func NewSafeList() *SafeList {
return &SafeList{L: list.New()}
}
//入隊
func (this *SafeList) PushFront(v interface{}) *list.Element {
this.Lock()
e := this.L.PushFront(v)
this.Unlock()
return e
}
//出隊
func (this *SafeList) PopBack() interface{} {
this.Lock()
if elem := this.L.Back(); elem != nil {
item := this.L.Remove(elem)
this.Unlock()
return item
}
this.Unlock()
return nil
}參考:http://www.dbjr.com.cn/jiaoben/2957122cc.htm
以上就是go內存隊列l(wèi)ist VS slice實現(xiàn)方式對比分析的詳細內容,更多關于go內存隊列l(wèi)ist slice的資料請關注腳本之家其它相關文章!
相關文章
go使用SQLX操作MySQL數(shù)據(jù)庫的教程詳解
sqlx 是 Go 語言中一個流行的操作數(shù)據(jù)庫的第三方包,它提供了對 Go 標準庫 database/sql 的擴展,簡化了操作數(shù)據(jù)庫的步驟,下面我們就來學習一下go如何使用SQLX實現(xiàn)MySQL數(shù)據(jù)庫的一些基本操作吧2023-11-11

