架构优化

This commit is contained in:
hahwu 2026-02-09 15:51:23 +08:00
parent b66bfa0209
commit 806780b5b3
6 changed files with 145 additions and 71 deletions

View File

@ -161,70 +161,71 @@ type Info struct {
} }
func (p *PlayroomMod) InitData() { func (p *PlayroomMod) InitData() {
InitCollect := playroomCfg.GetInitDecorate()
if p.Collect == nil { if p.Collect == nil {
p.Collect = make(map[int]int) p.Collect = make(map[int]int, 16)
} }
if p.Dress == nil { if p.Dress == nil {
p.Dress = make(map[int][]int) p.Dress = make(map[int][]int, 8)
} }
if p.DressSet == nil { if p.DressSet == nil {
p.DressSet = make(map[int]int) p.DressSet = make(map[int]int, 8)
} }
if p.GameInfo == nil { if p.GameInfo == nil {
p.GameInfo = make(map[int]interface{}) p.GameInfo = make(map[int]interface{}, 8)
} }
if p.NewCollect == nil { if p.NewCollect == nil {
p.NewCollect = make(map[int]*CollectInfo) p.NewCollect = make(map[int]*CollectInfo, len(InitCollect))
} }
InitCollect := playroomCfg.GetInitDecorate()
if len(p.NewCollect) == 0 { if len(p.NewCollect) == 0 {
now := GoUtil.Now()
for _, v := range InitCollect { for _, v := range InitCollect {
p.NewCollect[v] = &CollectInfo{ p.NewCollect[v] = &CollectInfo{
Id: v, Id: v,
AddTime: GoUtil.Now(), AddTime: now,
EndTime: 0, EndTime: 0,
Num: 1, Num: 1,
} }
} }
} }
if len(p.Collect) > 0 { if len(p.Collect) > 0 {
now := GoUtil.Now()
for k, v := range p.Collect { for k, v := range p.Collect {
p.NewCollect[k] = &CollectInfo{ p.NewCollect[k] = &CollectInfo{
Id: k, Id: k,
AddTime: GoUtil.Now(), AddTime: now,
EndTime: 0, EndTime: 0,
Num: v, Num: v,
} }
} }
p.Collect = make(map[int]int) p.Collect = nil
}
for _, v := range InitCollect {
p.Collect[v] = 1
} }
if p.Room == nil { if p.Room == nil {
p.Room = make(map[int]int) p.Room = make(map[int]int, 8)
p.JackpotNum = playroomCfg.GetJackpotNum() p.JackpotNum = playroomCfg.GetJackpotNum()
} }
if p.Visitor == nil { if p.Visitor == nil {
p.Visitor = make(map[int]*Info) p.Visitor = make(map[int]*Info, 16)
} }
if p.MoodInfo == nil { if p.MoodInfo == nil {
p.MoodInfo = make(map[int]*Mood) p.MoodInfo = make(map[int]*Mood, 4)
} }
if p.Physiology == nil { if p.Physiology == nil {
p.Physiology = make(map[int]*Physiology) p.Physiology = make(map[int]*Physiology, 4)
} }
if p.Reward == nil { if p.Reward == nil {
p.Reward = make([]*item.Item, 0) p.Reward = make([]*item.Item, 0, 8)
} }
if p.HasVisit == nil { if p.HasVisit == nil {
p.HasVisit = make(map[int]int64) p.HasVisit = make(map[int]int64, 16)
} }
if p.GameReward == nil { if p.GameReward == nil {
p.GameReward = make(map[int]*item.Item) p.GameReward = make(map[int]*item.Item, 4)
} }
if p.LoseItem == nil { if p.LoseItem == nil {
p.LoseItem = make([]*item.Item, 0) p.LoseItem = make([]*item.Item, 0, 8)
} }
if p.Flip == nil { if p.Flip == nil {
p.Flip = make(map[int]int) p.Flip = make(map[int]int)

View File

@ -207,9 +207,9 @@ func (p *Player) InitPlayer(UserName string) error {
p.lock.Lock() p.lock.Lock()
defer p.lock.Unlock() defer p.lock.Unlock()
p.msgChan = make(chan *MsgMod.Msg, 100) p.msgChan = make(chan *MsgMod.Msg, 100)
p.Msg = make([]PlayerMsg, 0) p.Msg = make([]PlayerMsg, 0, 16) // 添加容量提示
p.args = make(map[string]interface{}) p.args = make(map[string]interface{}, 8) // 添加容量提示
p.timerList = make(map[string]*timer.Timer) p.timerList = make(map[string]*timer.Timer, 8) // 添加容量提示
p.MDispatr = timer.NewDispatcher(100) p.MDispatr = timer.NewDispatcher(100)
p.stopSignal = make(chan bool) p.stopSignal = make(chan bool)
Base := &PlayerBaseData{p: p} Base := &PlayerBaseData{p: p}

View File

@ -45,13 +45,64 @@ import (
"time" "time"
) )
// buffer 对象池,复用 bytes.Buffer 减少内存分配 // encoderPair 封装 encoder 和 buffer
var bufferPool = sync.Pool{ type encoderPair struct {
encoder *gob.Encoder
buffer *bytes.Buffer
}
// decoderPair 封装 decoder 和 reader
type decoderPair struct {
decoder *gob.Decoder
reader *bytes.Reader
}
// gob 编码器对象池,复用 Encoder 减少反射开销
var gobEncoderPool = sync.Pool{
New: func() interface{} { New: func() interface{} {
return bytes.NewBuffer(make([]byte, 0, 128*1024)) buf := bytes.NewBuffer(make([]byte, 0, 128*1024))
return &encoderPair{
encoder: gob.NewEncoder(buf),
buffer: buf,
}
}, },
} }
// gob 解码器对象池,复用 Decoder 减少反射开销
var gobDecoderPool = sync.Pool{
New: func() interface{} {
reader := bytes.NewReader(nil)
return &decoderPair{
decoder: gob.NewDecoder(reader),
reader: reader,
}
},
}
// getEncoder 从对象池获取 encoder
func getEncoder() *encoderPair {
pair := gobEncoderPool.Get().(*encoderPair)
pair.buffer.Reset()
return pair
}
// putEncoder 归还 encoder 到对象池
func putEncoder(pair *encoderPair) {
gobEncoderPool.Put(pair)
}
// getDecoder 从对象池获取 decoder
func getDecoder(data []byte) *decoderPair {
pair := gobDecoderPool.Get().(*decoderPair)
pair.reader.Reset(data)
return pair
}
// putDecoder 归还 decoder 到对象池
func putDecoder(pair *decoderPair) {
gobDecoderPool.Put(pair)
}
type PlayerData struct { type PlayerData struct {
Name string Name string
IsHaveDataDb bool IsHaveDataDb bool
@ -158,11 +209,13 @@ func (p *PlayerModData) Reconnect(b bool) []byte {
func (p *PlayerModData) InitMod(player *Player) (bool, error) { func (p *PlayerModData) InitMod(player *Player) (bool, error) {
playerModList := PlayerModList{} playerModList := PlayerModList{}
if len(p.Data.ModData) > 0 { if len(p.Data.ModData) > 0 {
buf := bytes.NewBuffer(p.Data.ModData) // 从对象池获取 decoder
decoder := gob.NewDecoder(buf) pair := getDecoder(p.Data.ModData)
err := decoder.Decode(&playerModList) defer putDecoder(pair)
err := pair.decoder.Decode(&playerModList)
if err != nil { if err != nil {
log.Debug("playmod get data failed, err:%v\n", err) log.Debug("playmod get data failed, err:%v, uid=%d", err, player.M_DwUin)
return false, fmt.Errorf("playmod get data failed, err:%v", err) return false, fmt.Errorf("playmod get data failed, err:%v", err)
} }
} }
@ -241,64 +294,64 @@ func (p *PlayerMod) IsBlackList() bool {
func (p *PlayerMod) ClearData(player *Player) { func (p *PlayerMod) ClearData(player *Player) {
ChessMod := p.getChessMod() ChessMod := p.getChessMod()
if len(ChessMod.ChessMap) > 0 && len(ChessMod.ChessList) != len(ChessMod.ChessMap) { if len(ChessMod.ChessMap) > 0 && len(ChessMod.ChessList) != len(ChessMod.ChessMap) {
log.Debug("uid: %d, SaveData, chess error ", player.M_DwUin) log.Debug("uid: %d, SaveData, chess error", player.M_DwUin)
return return
} }
if p.is_update && !p.IsBlackList() { if p.is_update && !p.IsBlackList() {
//序列化模块 // 从对象池获取 encoder
buf := bufferPool.Get().(*bytes.Buffer) pair := getEncoder()
buf.Reset() // 清空之前的数据 defer putEncoder(pair)
encode := gob.NewEncoder(buf)
err := encode.Encode(p.mod_list) // 序列化模块
err := pair.encoder.Encode(p.mod_list)
if err != nil { if err != nil {
bufferPool.Put(buf) // 即使出错也要归还 log.Debug("uid: %d, SaveData, playmod encode error %v", player.M_DwUin, err)
log.Debug("uid: %d, SaveData, playmod error %v", player.M_DwUin, err)
return return
} }
// log.Debug("uid: %d, ClearData, playmod", player.M_DwUin)
// 复制数据,避免 buf 放回池后数据被清空
modDataBytes := make([]byte, pair.buffer.Len())
copy(modDataBytes, pair.buffer.Bytes())
modData := &db.SqlModStruct{ modData := &db.SqlModStruct{
DwUin: player.M_DwUin, DwUin: player.M_DwUin,
ModData: buf.Bytes(), ModData: modDataBytes,
UpdataTime: int32(time.Now().Unix()), UpdataTime: int32(time.Now().Unix()),
} }
err = db.SavePlayerModData(modData) err = db.SavePlayerModData(modData)
if err != nil { if err != nil {
bufferPool.Put(buf) // 即使出错也要归还 log.Debug("uid: %d, SaveData, db save error %v", player.M_DwUin, err)
log.Debug("uid: %d, SaveData, playmod error %v", player.M_DwUin, err)
return return
} }
p.is_update = false p.is_update = false
bufferPool.Put(buf) // 归还到对象池
} }
} }
func (p *PlayerMod) BackUp(B *PlayerBackUp) { func (p *PlayerMod) BackUp(B *PlayerBackUp) {
// 从对象池获取 buffer复用以减少内存分配 // 从对象池获取 encoder
buf := bufferPool.Get().(*bytes.Buffer) pair := getEncoder()
buf.Reset() // 清空之前的数据 defer putEncoder(pair)
encode := gob.NewEncoder(buf) err := pair.encoder.Encode(p.mod_list)
err := encode.Encode(p.mod_list)
if err != nil { if err != nil {
log.Debug("Backup, playmod error %v", err) log.Debug("Backup, playmod error %v", err)
bufferPool.Put(buf) // 即使出错也要归还
return return
} }
// 复制数据,因为 buf 会被放回池中 // 复制数据,因为 buf 会被放回池中
B.PlayMod = append([]byte(nil), buf.Bytes()...) B.PlayMod = make([]byte, pair.buffer.Len())
copy(B.PlayMod, pair.buffer.Bytes())
// 归还到对象池供下次使用
bufferPool.Put(buf)
} }
func (p *PlayerMod) Recover(B *PlayerBackUp) { func (p *PlayerMod) Recover(B *PlayerBackUp) {
if len(B.PlayMod) > 0 { if len(B.PlayMod) > 0 {
PlayMod := PlayerModList{} PlayMod := PlayerModList{}
buf := bytes.NewBuffer(B.PlayMod) // 从对象池获取 decoder
decoder := gob.NewDecoder(buf) pair := getDecoder(B.PlayMod)
err := decoder.Decode(&PlayMod) defer putDecoder(pair)
err := pair.decoder.Decode(&PlayMod)
if err != nil { if err != nil {
log.Debug("Recover, playmod error %v", err) log.Debug("Recover, playmod error %v", err)
return return

View File

@ -339,8 +339,6 @@ func UnitDecoratePartCost(p *Player) error {
fmt.Print(err) fmt.Print(err)
} }
return nil return nil
ChessMod := p.PlayMod.getChessMod()
return ChessMod.PutPartInBag(1515)
} }
func UnitOrderTrigger(p *Player) error { func UnitOrderTrigger(p *Player) error {

View File

@ -52,13 +52,15 @@ func RandStringMap(d map[string]int) string {
// 从d中随机选取n个元素 不放回 // 从d中随机选取n个元素 不放回
func RandMapNum(d map[int]int, n int) []int { func RandMapNum(d map[int]int, n int) []int {
if n <= 0 || n > len(d) { if n <= 0 {
return nil return nil
} }
if n == len(d) { if n >= len(d) {
r := make([]int, 0, len(d))
for k := range d { for k := range d {
return []int{k} r = append(r, k)
} }
return r
} }
r := make([]int, 0, n) r := make([]int, 0, n)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {

View File

@ -12,13 +12,13 @@ import (
func IntSlice(d interface{}) []int { func IntSlice(d interface{}) []int {
if d == nil { if d == nil {
return []int{} return nil
} }
// Type assertion with safety check // Type assertion with safety check
result, ok := d.([]int) result, ok := d.([]int)
if !ok { if !ok {
return []int{} return nil
} }
return result return result
} }
@ -77,12 +77,18 @@ func RandItem(slice []*item.Item) *item.Item {
} }
func RandSliceNum(s []int, num int) []int { func RandSliceNum(s []int, num int) []int {
if num <= 0 || len(s) == 0 {
return nil
}
if len(s) <= num {
result := make([]int, len(s))
copy(result, s)
return result
}
slice := make([]int, len(s)) slice := make([]int, len(s))
copy(slice, s) copy(slice, s)
r := make([]int, 0, num) r := make([]int, 0, num)
if num <= 0 || len(slice) < num {
return slice
}
for i := 0; i < num; i++ { for i := 0; i < num; i++ {
Id := rand.Intn(len(slice)) Id := rand.Intn(len(slice))
@ -93,12 +99,18 @@ func RandSliceNum(s []int, num int) []int {
} }
func RandSliceNum2(s []interface{}, num int) []interface{} { func RandSliceNum2(s []interface{}, num int) []interface{} {
if num <= 0 || len(s) == 0 {
return nil
}
if len(s) <= num {
result := make([]interface{}, len(s))
copy(result, s)
return result
}
slice := make([]interface{}, len(s)) slice := make([]interface{}, len(s))
copy(slice, s) copy(slice, s)
r := make([]interface{}, 0, num) r := make([]interface{}, 0, num)
if num <= 0 || len(slice) < num {
return slice
}
for i := 0; i < num; i++ { for i := 0; i < num; i++ {
Id := rand.Intn(len(slice)) Id := rand.Intn(len(slice))
@ -125,7 +137,7 @@ func RandSliceNumNonAdjacent(s []int, num int) []int {
} }
func SubAdjacentElemSlice(s []int, Id int) []int { func SubAdjacentElemSlice(s []int, Id int) []int {
r := make([]int, 0, len(s)) r := make([]int, 0)
for k, v := range s { for k, v := range s {
if k < Id-1 || k > Id+1 { if k < Id-1 || k > Id+1 {
r = append(r, v) r = append(r, v)
@ -145,7 +157,7 @@ func RandStringSlice(slice []string) string {
func SliceStringToInt(s []string) []int { func SliceStringToInt(s []string) []int {
if len(s) == 0 { if len(s) == 0 {
return []int{} return nil
} }
r := make([]int, 0, len(s)) r := make([]int, 0, len(s))
for _, v := range s { for _, v := range s {
@ -297,6 +309,7 @@ func SlicesEqualString(a, b []string) bool {
} }
// IsContainSlice checks if all elements of s2 are contained in s. // IsContainSlice checks if all elements of s2 are contained in s.
// 注意此函数会考虑重复元素s2中的每个元素在s中必须有对应数量
func IsContainSlice(s []int, s2 []int) bool { func IsContainSlice(s []int, s2 []int) bool {
if len(s2) == 0 { if len(s2) == 0 {
return true return true
@ -352,7 +365,14 @@ func ShuffleArray(s []int) []int {
return r return r
} }
// IsContain 与 IsContainSlice 功能相同,建议使用 IsContainSlice
func IsContain(s []int, s2 []int) bool { func IsContain(s []int, s2 []int) bool {
if len(s2) == 0 {
return true
}
if len(s) < len(s2) {
return false
}
for _, v := range s2 { for _, v := range s2 {
if !InArray(v, s) { if !InArray(v, s) {
return false return false