Skip to content

Commit

Permalink
feat: optimize list struct
Browse files Browse the repository at this point in the history
  • Loading branch information
xgzlucario committed Oct 30, 2024
1 parent b7fc868 commit ff8ca73
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 72 deletions.
4 changes: 2 additions & 2 deletions ae.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package main

import (
"errors"
"github.com/xgzlucario/rotom/internal/dict"
"golang.org/x/sys/unix"
"time"
)

type TeType int
Expand Down Expand Up @@ -95,7 +95,7 @@ func (loop *AeLoop) ModDetach(fd int) {
}

func GetMsTime() int64 {
return dict.GetNanoTime() / 1e6
return time.Now().UnixMilli()
}

func (loop *AeLoop) AddTimeEvent(mask TeType, interval int64, proc TimeProc, extra interface{}) int {
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
github.com/stretchr/testify v1.9.0
github.com/tidwall/mmap v0.3.0
github.com/yuin/gopher-lua v1.1.1
github.com/zyedidia/generic v1.2.1
golang.org/x/sys v0.26.0
)

Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M=
github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
github.com/zyedidia/generic v1.2.1 h1:Zv5KS/N2m0XZZiuLS82qheRG4X1o5gsWreGb0hR7XDc=
github.com/zyedidia/generic v1.2.1/go.mod h1:ly2RBz4mnz1yeuVbQA/VFwGjK3mnHGRj1JuoG336Bis=
golang.org/x/arch v0.11.0 h1:KXV8WWKCXm6tRpLirl2szsO5j/oOODwZf4hATmGVNs4=
golang.org/x/arch v0.11.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
Expand Down
122 changes: 52 additions & 70 deletions internal/list/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package list

import (
"github.com/bytedance/sonic"
"github.com/zyedidia/generic/list"
"io"
)

Expand All @@ -13,77 +14,61 @@ import (
// QuickList is double linked listpack, implement redis quicklist data structure,
// based on listpack rather than ziplist to optimize cascade update.
type QuickList struct {
size int
head, tail *Node
}

type Node struct {
*ListPack
prev, next *Node
size int
ls *list.List[*ListPack] // linked-list
}

// New create a quicklist instance.
func New() *QuickList {
n := newNode()
return &QuickList{head: n, tail: n}
ls := list.New[*ListPack]()
ls.PushFront(NewListPack())
return &QuickList{ls: ls}
}

func (ls *QuickList) head() *ListPack {
return ls.ls.Front.Value
}

func newNode() *Node {
return &Node{ListPack: NewListPack()}
func (ls *QuickList) tail() *ListPack {
return ls.ls.Back.Value
}

func (ls *QuickList) LPush(key string) {
if len(ls.head.data)+len(key) >= maxListPackSize {
n := newNode()
n.next = ls.head
ls.head.prev = n
ls.head = n
if len(ls.head().data)+len(key) >= maxListPackSize {
ls.ls.PushFront(NewListPack())
}
ls.size++
ls.head.LPush(key)
ls.head().LPush(key)
}

func (ls *QuickList) RPush(key string) {
if len(ls.tail.data)+len(key) >= maxListPackSize {
n := newNode()
ls.tail.next = n
n.prev = ls.tail
ls.tail = n
if len(ls.tail().data)+len(key) >= maxListPackSize {
ls.ls.PushBack(NewListPack())
}
ls.size++
ls.tail.RPush(key)
ls.tail().RPush(key)
}

func (ls *QuickList) LPop() (key string, ok bool) {
for lp := ls.head; lp != nil; lp = lp.next {
if lp.size > 0 {
ls.size--
return lp.LPop()
}
ls.free(lp)
if ls.Size() == 0 {
return
}
return
for n := ls.ls.Front; n != nil && n.Value.size == 0; n = n.Next {
ls.ls.Remove(n)
}
ls.size--
return ls.head().LPop()
}

func (ls *QuickList) RPop() (key string, ok bool) {
for lp := ls.tail; lp != nil; lp = lp.prev {
if lp.size > 0 {
ls.size--
return lp.RPop()
}
ls.free(lp)
if ls.Size() == 0 {
return
}
return
}

// free release empty list node.
func (ls *QuickList) free(n *Node) {
if n.prev != nil && n.next != nil {
n.prev.next = n.next
n.next.prev = n.prev
bpool.Put(n.data)
n = nil
for n := ls.ls.Back; n != nil && n.Value.size == 0; n = n.Prev {
ls.ls.Remove(n)
}
ls.size--
return ls.tail().RPop()
}

func (ls *QuickList) Size() int { return ls.size }
Expand Down Expand Up @@ -113,23 +98,23 @@ func (ls *QuickList) Range(start, stop int, fn func(data []byte)) {
start += ls.Size()
}

lp := ls.head
for lp != nil && start > lp.Size() {
start -= lp.Size()
lp = lp.next
lp := ls.ls.Front
for lp != nil && start > lp.Value.Size() {
start -= lp.Value.Size()
lp = lp.Next
}
if lp == nil {
return
}
it := lp.Iterator()

it := lp.Value.Iterator()
for range start {
it.Next()
}

for range count {
if it.IsLast() {
lp = lp.next
it = lp.Iterator()
lp = lp.Next
it = lp.Value.Iterator()
}
fn(it.Next())
}
Expand All @@ -142,8 +127,11 @@ type ListPackData struct {

func (ls *QuickList) Encode(writer io.Writer) error {
var data []ListPackData
for p := ls.head; p != nil; p = p.next {
data = append(data, ListPackData{Data: p.data, Size: p.size})
for n := ls.ls.Front; n != nil; n = n.Next {
data = append(data, ListPackData{
Data: n.Value.data,
Size: n.Value.size,
})
}
return sonic.ConfigDefault.NewEncoder(writer).Encode(data)
}
Expand All @@ -153,23 +141,17 @@ func (ls *QuickList) Decode(src []byte) error {
if err := sonic.Unmarshal(src, &datas); err != nil {
return err
}
// init
ls.size = 0
ls.ls = list.New[*ListPack]()

// head node
n := newNode()
n.size = datas[0].Size
n.data = datas[0].Data
ls.head = n
ls.tail = n
cur := n

for _, data := range datas[1:] {
n := newNode()
for _, data := range datas {
n := NewListPack()
n.size = data.Size
n.data = data.Data
cur.next = n
n.prev = cur
ls.tail = n
cur = n

ls.size += int(data.Size)
ls.ls.PushBack(n)
}
return nil
}
18 changes: 18 additions & 0 deletions internal/list/list_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package list

import (
"bytes"
"slices"
"strconv"
"testing"
Expand Down Expand Up @@ -135,4 +136,21 @@ func TestList(t *testing.T) {
assert.Equal(i, 101)
}
})

t.Run("encode", func(t *testing.T) {
ls := genList(0, N)
buf := bytes.NewBuffer(nil)
err := ls.Encode(buf)
assert.Nil(err)

ls2 := New()
err = ls2.Decode(buf.Bytes())
assert.Nil(err)

i := 0
ls.Range(0, N, func(data []byte) {
assert.Equal(string(data), genKey(i))
i++
})
})
}

0 comments on commit ff8ca73

Please sign in to comment.