Skip to content

Commit 64ead60

Browse files
committed
性能优化
1 parent 448dbc4 commit 64ead60

File tree

4 files changed

+50
-56
lines changed

4 files changed

+50
-56
lines changed

go.mod

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@ module github.com/antlabs/timer
22

33
go 1.13
44

5-
require gopkg.in/go-playground/assert.v1 v1.2.1
5+
require (
6+
github.com/antlabs/stl v0.0.1
7+
gopkg.in/go-playground/assert.v1 v1.2.1
8+
)

go.sum

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,10 @@
1+
github.com/antlabs/stl v0.0.1 h1:TRD3csCrjREeLhLoQ/supaoCvFhNLBTNIwuRGrDIs6Q=
2+
github.com/antlabs/stl v0.0.1/go.mod h1:wvVwP1loadLG3cRjxUxK8RL4Co5xujGaZlhbztmUEqQ=
3+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
5+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
6+
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
7+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
18
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
29
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
10+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

time_wheel.go

Lines changed: 25 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package timer
22

33
import (
4-
"container/list"
54
"context"
65
"fmt"
76
"sync/atomic"
87
"time"
8+
"unsafe"
9+
10+
"github.com/antlabs/stl/list"
911
)
1012

1113
const (
@@ -57,12 +59,13 @@ func newTimeWheel() *timeWheel {
5759
func (t *timeWheel) init() {
5860

5961
for i := 0; i < nearSize; i++ {
60-
t.t1[i] = &Time{List: list.New()}
62+
t.t1[i] = newTimeHead()
63+
6164
}
6265

6366
for i := 0; i < 4; i++ {
6467
for j := 0; j < levelSize; j++ {
65-
t.t2Tot5[i][j] = &Time{List: list.New()}
68+
t.t2Tot5[i][j] = newTimeHead()
6669
}
6770
}
6871

@@ -161,27 +164,21 @@ func (t *timeWheel) Stop() {
161164
// 移动链表
162165
func (t *timeWheel) cascade(levelIndex int, index int) {
163166

164-
tmp := list.New()
167+
tmp := newTimeHead()
165168

166169
l := t.t2Tot5[levelIndex][index]
167170
l.Lock()
168171

169-
for e := l.Front(); e != nil; {
170-
next := e.Next()
171-
l.Remove(e)
172-
173-
tmp.PushBack(e.Value)
174-
175-
e = next
176-
}
177-
178-
t.t2Tot5[levelIndex][index].Init()
172+
l.ReplaceInit(&tmp.Head)
179173

180174
l.Unlock()
181175

182-
for e := tmp.Front(); e != nil; e = e.Next() {
183-
t.add(e.Value.(*timeNode), atomic.LoadUint64(&t.jiffies))
184-
}
176+
offset := unsafe.Offsetof(tmp.Head)
177+
tmp.ForEachSafe(func(pos *list.Head) {
178+
node := (*timeNode)(pos.Entry(offset))
179+
t.add(node, atomic.LoadUint64(&t.jiffies))
180+
})
181+
185182
}
186183

187184
func (t *timeWheel) moveTot1(head *Time, index uint64) {
@@ -190,15 +187,7 @@ func (t *timeWheel) moveTot1(head *Time, index uint64) {
190187
t1.Lock()
191188
defer t1.Unlock()
192189

193-
for e := t1.Front(); e != nil; {
194-
next := e.Next()
195-
196-
t1.Remove(e)
197-
head.PushBack(e.Value)
198-
e = next
199-
}
200-
201-
t.t1[index].List.Init()
190+
t1.ReplaceInit(&head.Head)
202191
}
203192

204193
// moveAndExec函数功能
@@ -229,31 +218,31 @@ func (t *timeWheel) moveAndExec() {
229218
atomic.AddUint64(&t.jiffies, 1)
230219

231220
t.t1[index].Lock()
232-
if t.t1[index].List.Len() == 0 {
221+
if t.t1[index].Len() == 0 {
233222
t.t1[index].Unlock()
234223
return
235224
}
225+
236226
t.t1[index].Unlock()
237227

238-
head := Time{List: list.New()}
239-
t.moveTot1(&head, index)
228+
head := newTimeHead()
229+
t.moveTot1(head, index)
240230
// 执行
241231

242-
for e := head.Front(); e != nil; {
243-
244-
val := e.Value.(*timeNode)
245-
next := e.Next()
246-
head.Remove(e)
247-
e = next
232+
offset := unsafe.Offsetof(head.Head)
248233

234+
head.ForEachSafe(func(pos *list.Head) {
235+
val := (*timeNode)(pos.Entry(offset))
236+
head.Del(pos)
249237
go val.callback()
250238

251239
if val.isSchedule {
252240
jiffies := t.jiffies
253241
val.expire = uint64(t.getExpire(val.userExpire, jiffies))
254242
t.add(val, jiffies)
255243
}
256-
}
244+
})
245+
257246
}
258247

259248
func (t *timeWheel) run() {

time_wheel_node.go

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package timer
22

33
import (
4-
"container/list"
54
"sync"
65
"sync/atomic"
76
"time"
7+
8+
"github.com/antlabs/stl/list"
89
)
910

1011
const (
@@ -16,19 +17,24 @@ const (
1617
// 先使用sync.Mutex实现功能
1718
// 后面使用cas优化
1819
type Time struct {
19-
*list.List
20-
20+
timeNode
2121
sync.Mutex
2222
}
2323

24+
func newTimeHead() *Time {
25+
head := &Time{}
26+
head.Init()
27+
return head
28+
}
29+
2430
func (t *Time) lockPushBack(node *timeNode) {
2531
t.Lock()
2632
defer t.Unlock()
2733
if atomic.LoadUint32(&node.lock) == haveStop {
2834
return
2935
}
3036

31-
node.element = t.PushBack(node)
37+
t.AddTail(&node.Head)
3238
node.list = t
3339
}
3440

@@ -40,20 +46,10 @@ type timeNode struct {
4046
close uint32
4147
lock uint32
4248

43-
list *Time
44-
element *list.Element
45-
}
49+
list *Time
4650

47-
/*
48-
func (t *timeNode) grab() {
49-
for {
50-
prevVal := atomic.LoadUint32(&t.lock)
51-
if atomic.CompareAndSwapUint32(&t.lock, prevVal, stopGrab) {
52-
break
53-
}
54-
}
51+
list.Head
5552
}
56-
*/
5753

5854
func (t *timeNode) Stop() {
5955
//这里和32行是竞争关系,拷贝一个副本,防止出现unlock unlock的情况
@@ -63,7 +59,5 @@ func (t *timeNode) Stop() {
6359

6460
atomic.StoreUint32(&t.close, haveStop)
6561

66-
//t.grab()
67-
68-
t.list.Remove(t.element)
62+
t.list.Del(&t.Head)
6963
}

0 commit comments

Comments
 (0)