私はGoに小さなゲームサーバーを作成しようとしています。私は基本的にWebSocketライブラリ(https://github.com/gorilla/websocket)からサンプルをコピーしました。Go - ゴルーチン間の高性能通信?
毎秒、サーバは機能s.tick()
を実行し、現在時刻をユーザに送信します。これは、ユーザーが操作を実行していないときにうまく動作します。
ユーザが参加、メッセージを送信、またはメッセージを送信すると、情報は3つのチャネルの1つ(各アクションに1つ)で送信され、対応するアクションが実行されますが、s.tick()
はスキップまたは遅延します。私は、ユーザーがいつもアクションを実行すると、s.tick()
は決して呼び出されないことに気付きました。ここで
Mon, 05 Dec 2016 20:19:11 CET
Mon, 05 Dec 2016 20:19:12 CET
Mon, 05 Dec 2016 20:19:13 CET
Mon, 05 Dec 2016 20:19:15 CET
Mon, 05 Dec 2016 20:19:16 CET
Mon, 05 Dec 2016 20:19:17 CET
-- users joining and leaving
Mon, 05 Dec 2016 20:19:25 CET
Mon, 05 Dec 2016 20:19:26 CET
Mon, 05 Dec 2016 20:19:27 CET
Mon, 05 Dec 2016 20:19:28 CET
Mon, 05 Dec 2016 20:19:29 CET
私はアクション間そんなに遅延を引き起こしているかどうか確認してみました(これらのアクションのどれも時間がかかっていない)と私の唯一の思想があること:
- 私のコードは、ゴーのチャンネルが
I cが遅い
type GameServer struct {
players map[*Player]bool
register chan *Player
unregister chan *Player
broadcast chan []byte
ticker *time.Ticker //use a single "global" *time.Ticker
}
func (s *GameServer) broadcastMessage(msg []byte) {
for player := range s.players {
player.messages <- msg
}
}
func (s *GameServer) tick() {
s.broadcastMessage([]byte(time.Now().Format(time.RFC1123)))
}
// question is mostly related to this function
func (s *GameServer) run() {
for {
select {
case _ = <- s.Ticker.C: //use the "global" *time.Ticker instead of creating a new one every time
s.tick()
case client := <-s.register:
s.players[client] = true
case client := <-s.unregister:
delete(s.players, client)
case msg := <-s.broadcast:
s.broadcastMessage(msg)
}
}
}
:
type GameServer struct {
players map[*Player]bool
register chan *Player
unregister chan *Player
broadcast chan []byte
}
func (s *GameServer) broadcastMessage(msg []byte) {
for player := range s.players {
player.messages <- msg
}
}
func (s *GameServer) tick() {
s.broadcastMessage([]byte(time.Now().Format(time.RFC1123)))
}
// question is mostly related to this function
func (s *GameServer) run() {
for {
select {
case _ = <-time.NewTicker(time.Second).C:
s.tick()
case client := <-s.register:
s.players[client] = true
case client := <-s.unregister:
delete(s.players, client)
case msg := <-s.broadcast:
s.broadcastMessage(msg)
}
}
}
GameServerの構造体にグローバルタイムティッカーを追加する必要があります。これは、初期化されるのは一度だけです。最初の選択ケースを 's.ticker.C'に変更してください。現時点では、run関数が呼び出されるたびに新しいティッカーを作成しています。したがって、runが呼び出されてから少なくとも1秒間、他のチャネルにデータがないインスタンスでtickが実行されます。見ている。 – 0xor1
あなたはすべての反復で新しいティッカーを作成していますので、安定したティック間隔を持たずにリソースを漏らしてしまいます。 – JimB