架构优化
This commit is contained in:
parent
b66bfa0209
commit
806780b5b3
@ -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)
|
||||||
|
|||||||
@ -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}
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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++ {
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user