go內(nèi)存隊(duì)列l(wèi)ist VS slice實(shí)現(xiàn)方式對比分析
go隊(duì)列的實(shí)現(xiàn)方式
golang中沒有隊(duì)列這種數(shù)據(jù)結(jié)構(gòu),通常需要自己實(shí)現(xiàn),常見的可以通過list或slice實(shí)現(xiàn)。
list是"container/list"中的數(shù)據(jù)結(jié)構(gòu),用雙向鏈表實(shí)現(xiàn),可以用來做隊(duì)列:
//入隊(duì) func (l *List) PushBack(v interface{}) *Element //出隊(duì):先Front()取得頭,然后Remove()刪除 func (l *List) Front() *Element func (l *List) Remove(e *Element) interface{}
slice實(shí)現(xiàn)隊(duì)列的方式:
var s []obj s = append(s, obj) //入隊(duì) s = s[1:] //出隊(duì)
benchmark測試比較
benchmark測試代碼: 隊(duì)列中存入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測試代碼:隊(duì)列中存入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測試結(jié)果
# 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
結(jié)論:
- 不管用list還是slice,隊(duì)列中存儲對象指針的性能,要好于直接存儲對象;
- slice實(shí)現(xiàn)的隊(duì)列,存儲指針對象時(shí)性能最好;
- list實(shí)現(xiàn)的隊(duì)列,不管是存儲對象還是指針對象,其性能差異不是太大;
Open-falcon的隊(duì)列實(shí)現(xiàn)
open-falcon使用list和mutex實(shí)現(xiàn)了一個(gè)協(xié)程安全的內(nèi)存隊(duì)列。
實(shí)現(xiàn)代碼:https://github.com/toolkits/c...
type SafeList struct { sync.RWMutex L *list.List } func NewSafeList() *SafeList { return &SafeList{L: list.New()} } //入隊(duì) func (this *SafeList) PushFront(v interface{}) *list.Element { this.Lock() e := this.L.PushFront(v) this.Unlock() return e } //出隊(duì) 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內(nèi)存隊(duì)列l(wèi)ist VS slice實(shí)現(xiàn)方式對比分析的詳細(xì)內(nèi)容,更多關(guān)于go內(nèi)存隊(duì)列l(wèi)ist slice的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Go中使用操作符進(jìn)行數(shù)學(xué)運(yùn)算的示例代碼
在編程中有效地執(zhí)行數(shù)學(xué)運(yùn)算是一項(xiàng)需要開發(fā)的重要技能,本文主要介紹了Go中使用操作符進(jìn)行數(shù)學(xué)運(yùn)算的示例代碼,具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10go使用SQLX操作MySQL數(shù)據(jù)庫的教程詳解
sqlx 是 Go 語言中一個(gè)流行的操作數(shù)據(jù)庫的第三方包,它提供了對 Go 標(biāo)準(zhǔn)庫 database/sql 的擴(kuò)展,簡化了操作數(shù)據(jù)庫的步驟,下面我們就來學(xué)習(xí)一下go如何使用SQLX實(shí)現(xiàn)MySQL數(shù)據(jù)庫的一些基本操作吧2023-11-11Go習(xí)慣用法(多值賦值短變量聲明賦值簡寫模式)基礎(chǔ)實(shí)例
本文為大家介紹了Go習(xí)慣用法(多值賦值,短變量聲明和賦值,簡寫模式、多值返回函數(shù)、comma,ok 表達(dá)式、傳值規(guī)則)的基礎(chǔ)實(shí)例,幫大家鞏固扎實(shí)Go語言基礎(chǔ)2024-01-01Golang負(fù)載均衡和?;钤O(shè)計(jì)原理示例探究
這篇文章主要為大家介紹了Golang負(fù)載均衡和?;钤O(shè)計(jì)原理示例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01