perf: 移除 lockstep 对 timer.Ticket 的依赖,更改为 time.Ticker 实现,减少不必要的资源占用
This commit is contained in:
parent
508e30fb5b
commit
9038bfc2b5
|
@ -2,7 +2,6 @@ package lockstep
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/kercylan98/minotaur/utils/timer"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -11,7 +10,6 @@ import (
|
||||||
func NewLockstep[ClientID comparable, Command any](options ...Option[ClientID, Command]) *Lockstep[ClientID, Command] {
|
func NewLockstep[ClientID comparable, Command any](options ...Option[ClientID, Command]) *Lockstep[ClientID, Command] {
|
||||||
lockstep := &Lockstep[ClientID, Command]{
|
lockstep := &Lockstep[ClientID, Command]{
|
||||||
currentFrame: -1,
|
currentFrame: -1,
|
||||||
ticker: timer.GetTicker(10),
|
|
||||||
frameRate: 15,
|
frameRate: 15,
|
||||||
serialization: func(frame int64, commands []Command) []byte {
|
serialization: func(frame int64, commands []Command) []byte {
|
||||||
frameStruct := struct {
|
frameStruct := struct {
|
||||||
|
@ -55,7 +53,7 @@ type Lockstep[ClientID comparable, Command any] struct {
|
||||||
|
|
||||||
frameCache map[int64][]byte // 帧序列化缓存
|
frameCache map[int64][]byte // 帧序列化缓存
|
||||||
frameCacheLock sync.RWMutex // 帧序列化缓存锁
|
frameCacheLock sync.RWMutex // 帧序列化缓存锁
|
||||||
ticker *timer.Ticker // 定时器
|
ticker *time.Ticker // 定时器
|
||||||
|
|
||||||
lockstepStoppedEventHandles []StoppedEventHandle[ClientID, Command]
|
lockstepStoppedEventHandles []StoppedEventHandle[ClientID, Command]
|
||||||
}
|
}
|
||||||
|
@ -124,48 +122,51 @@ func (slf *Lockstep[ClientID, Command]) StartBroadcast() {
|
||||||
}
|
}
|
||||||
slf.running = true
|
slf.running = true
|
||||||
if slf.ticker == nil {
|
if slf.ticker == nil {
|
||||||
slf.ticker = timer.GetTicker(10)
|
slf.ticker = time.NewTicker(time.Second / time.Duration(slf.frameRate))
|
||||||
}
|
}
|
||||||
slf.runningLock.Unlock()
|
slf.runningLock.Unlock()
|
||||||
slf.currentFrame = slf.initFrame
|
slf.currentFrame = slf.initFrame
|
||||||
|
|
||||||
slf.ticker.Loop("lockstep", timer.Instantly, time.Second/time.Duration(slf.frameRate), timer.Forever, func() {
|
go func(ls *Lockstep[ClientID, Command]) {
|
||||||
|
for range ls.ticker.C {
|
||||||
slf.currentFrameLock.RLock()
|
go func(ls *Lockstep[ClientID, Command]) {
|
||||||
if slf.frameLimit > 0 && slf.currentFrame >= slf.frameLimit {
|
ls.currentFrameLock.RLock()
|
||||||
slf.currentFrameLock.RUnlock()
|
if ls.frameLimit > 0 && ls.currentFrame >= ls.frameLimit {
|
||||||
slf.StopBroadcast()
|
ls.currentFrameLock.RUnlock()
|
||||||
return
|
ls.StopBroadcast()
|
||||||
}
|
return
|
||||||
slf.currentFrameLock.RUnlock()
|
|
||||||
slf.currentFrameLock.Lock()
|
|
||||||
slf.currentFrame++
|
|
||||||
currentFrame := slf.currentFrame
|
|
||||||
currentCommands := slf.currentCommands
|
|
||||||
slf.currentCommands = make([]Command, 0, len(currentCommands))
|
|
||||||
slf.currentFrameLock.Unlock()
|
|
||||||
|
|
||||||
slf.clientLock.RLock()
|
|
||||||
defer slf.clientLock.RUnlock()
|
|
||||||
slf.frameCacheLock.Lock()
|
|
||||||
defer slf.frameCacheLock.Unlock()
|
|
||||||
|
|
||||||
for clientId, client := range slf.clients {
|
|
||||||
var i = slf.clientFrame[clientId]
|
|
||||||
if i < slf.initFrame {
|
|
||||||
i = slf.initFrame
|
|
||||||
}
|
|
||||||
for ; i < currentFrame; i++ {
|
|
||||||
cache, exist := slf.frameCache[i]
|
|
||||||
if !exist {
|
|
||||||
cache = slf.serialization(i, currentCommands)
|
|
||||||
slf.frameCache[i] = cache
|
|
||||||
}
|
}
|
||||||
client.Write(cache)
|
ls.currentFrameLock.RUnlock()
|
||||||
}
|
ls.currentFrameLock.Lock()
|
||||||
slf.clientFrame[clientId] = currentFrame
|
ls.currentFrame++
|
||||||
|
currentFrame := ls.currentFrame
|
||||||
|
currentCommands := ls.currentCommands
|
||||||
|
ls.currentCommands = make([]Command, 0, len(currentCommands))
|
||||||
|
ls.currentFrameLock.Unlock()
|
||||||
|
|
||||||
|
ls.clientLock.RLock()
|
||||||
|
defer ls.clientLock.RUnlock()
|
||||||
|
ls.frameCacheLock.Lock()
|
||||||
|
defer ls.frameCacheLock.Unlock()
|
||||||
|
|
||||||
|
for clientId, client := range ls.clients {
|
||||||
|
var i = ls.clientFrame[clientId]
|
||||||
|
if i < ls.initFrame {
|
||||||
|
i = ls.initFrame
|
||||||
|
}
|
||||||
|
for ; i < currentFrame; i++ {
|
||||||
|
cache, exist := ls.frameCache[i]
|
||||||
|
if !exist {
|
||||||
|
cache = ls.serialization(i, currentCommands)
|
||||||
|
ls.frameCache[i] = cache
|
||||||
|
}
|
||||||
|
client.Write(cache)
|
||||||
|
}
|
||||||
|
ls.clientFrame[clientId] = currentFrame
|
||||||
|
}
|
||||||
|
}(ls)
|
||||||
}
|
}
|
||||||
})
|
}(slf)
|
||||||
}
|
}
|
||||||
|
|
||||||
// StopBroadcast 停止广播
|
// StopBroadcast 停止广播
|
||||||
|
@ -179,7 +180,7 @@ func (slf *Lockstep[ClientID, Command]) StopBroadcast() {
|
||||||
slf.runningLock.Unlock()
|
slf.runningLock.Unlock()
|
||||||
|
|
||||||
if slf.ticker != nil {
|
if slf.ticker != nil {
|
||||||
slf.ticker.Release()
|
slf.ticker.Stop()
|
||||||
}
|
}
|
||||||
slf.ticker = nil
|
slf.ticker = nil
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue