Переглянути джерело

maak robuster, zet cpu profile aan voor aanmaken games

Harry de Boer 10 роки тому
батько
коміт
d4c00f9ef5
3 змінених файлів з 47 додано та 25 видалено
  1. 1 1
      battlecamp-go-boardgenerator/main.go
  2. 33 20
      board/board.go
  3. 13 4
      games/game.go

+ 1 - 1
battlecamp-go-boardgenerator/main.go

@@ -37,7 +37,7 @@ func generateBoard(w http.ResponseWriter, r *http.Request) {
 	totalWidth, _ := strconv.Atoi(r.FormValue("totalWidth"))
 	totalHeight, _ := strconv.Atoi(r.FormValue("totalHeight"))
 	log.Printf("Creating partial x=%v, y=%v, width=%v, height=%v, totalWidth=%v, totalHeight=%v", x, y, width, height, totalWidth, totalHeight)
-	b := board.NewPartial(x, y, width, height, totalWidth, totalHeight)
+	b := board.NewRegion(x, y, width, height, totalWidth, totalHeight)
 	b.WriteData(w)
 }
 

+ 33 - 20
board/board.go

@@ -37,12 +37,12 @@ const (
 
 // Create a new randomly generated board.
 func New(width, height int) *Board {
-	return NewPartial(0, 0, width, height, width, height)
+	return NewRegion(0, 0, width, height, width, height)
 }
 
-func NewPartial(startX, startY, width, height, totalWidth, totalHeight int) *Board {
+func NewRegion(startX, startY, width, height, totalWidth, totalHeight int) *Board {
 	r := rand.New(rand.NewSource(time.Now().UnixNano() + int64(startY+startY)))
-	return newPartial(startX, startY, width, height, totalWidth, totalHeight, r)
+	return newRegion(startX, startY, width, height, totalWidth, totalHeight, r)
 }
 
 func NewRemote(width, height int) *Board {
@@ -52,20 +52,26 @@ func NewRemote(width, height int) *Board {
 	xRegions := (width + (regionWidth - 1)) / regionWidth
 	yRegions := (height + (regionHeight - 1)) / regionHeight
 
-	returnChan := make(chan response, 32)
+	returnChan := make(chan *response, 32)
 	defer close(returnChan)
 	go b.genRegions(xRegions, yRegions, returnChan)
 
 	for answers := 0; xRegions*yRegions > answers; answers++ {
 		result := <-returnChan
 		log.Printf("Received partial: x=%v, y=%v, width=%v, height=%v\n", result.x, result.y, result.width, result.height)
+
+		if result.boardTile == nil {
+			continue
+		}
+
 		for ry := 0; ry < result.height; ry++ {
 			i, _ := b.xyToIndex(result.x, result.y+ry)
-			_, err := result.boardTile.Read(b.data[i : i+byteIndex(result.width)])
+			n, err := result.boardTile.Read(b.data[i : i+byteIndex(result.width)])
 			if !(err == nil || err == io.EOF) {
-				log.Printf("ERROR: %v", err)
+				log.Printf("ERROR after reading %v bytes: %v\n", n, err)
 			}
 		}
+
 		result.boardTile.Close()
 	}
 
@@ -90,10 +96,10 @@ type work struct {
 	height int
 }
 
-func (b *Board) genRegions(xRegions, yRegions int, responseChan chan response) {
-	const numWorkers = 50
+func (b *Board) genRegions(xRegions, yRegions int, responseChan chan *response) {
+	const numWorkers = 32
 
-	workChan := make(chan work, numWorkers)
+	workChan := make(chan *work, numWorkers)
 
 	for i := 0; i < numWorkers; i++ {
 		go worker(workChan, responseChan)
@@ -103,13 +109,13 @@ func (b *Board) genRegions(xRegions, yRegions int, responseChan chan response) {
 		for j := 0; j < yRegions; j++ {
 			x := i * regionWidth
 			y := j * regionHeight
-			workChan <- work{x, y, b.Width, b.Height}
+			workChan <- &work{x, y, b.Width, b.Height}
 		}
 	}
 
 }
 
-func worker(workChan chan work, responseChan chan response) {
+func worker(workChan chan *work, responseChan chan *response) {
 
 	for w, open := <-workChan; open; w, open = <-workChan {
 		var partialWidth, partialHeight int
@@ -129,20 +135,27 @@ func worker(workChan chan work, responseChan chan response) {
 		log.Printf("Requested generation of tile with url: %v\n", requestUrl)
 
 		resp, err := http.Get(requestUrl)
-		for err != nil {
-			log.Printf("ERROR requesting region: %v", err)
+		const maxRetries = 3
+		for retries := 1; err != nil && retries < maxRetries; retries++ {
+			log.Printf("ERROR requesting region (try %v) : %v", retries, err)
+			time.Sleep(50 * time.Millisecond)
 			resp, err = http.Get(requestUrl)
 		}
 
-		result := response{
+		var r io.ReadCloser
+		if err == nil {
+			r = resp.Body
+		} else {
+			log.Printf("ERROR requesting region, skipping (try %v) : %v", maxRetries, err)
+		}
+
+		responseChan <- &response{
 			x:         w.x,
 			y:         w.y,
 			width:     partialHeight,
 			height:    partialHeight,
-			boardTile: resp.Body,
+			boardTile: r,
 		}
-
-		responseChan <- result
 	}
 }
 
@@ -173,7 +186,7 @@ func (b *Board) WriteData(w io.Writer) {
 	n, err := w.Write(b.data)
 
 	if err != nil {
-		fmt.Errorf("Error writing board after %v bytes: %v", n, err)
+		log.Printf("Error writing board after %v bytes: %v", n, err)
 	}
 }
 
@@ -217,10 +230,10 @@ func newBlank(width, height int) *Board {
 }
 
 func new(width, height int, r *rand.Rand) *Board {
-	return newPartial(0, 0, width, height, width, height, r)
+	return newRegion(0, 0, width, height, width, height, r)
 }
 
-func newPartial(startX, startY, width, height, totalWidth, totalHeight int, r *rand.Rand) *Board {
+func newRegion(startX, startY, width, height, totalWidth, totalHeight int, r *rand.Rand) *Board {
 	b := newBlank(width, height)
 	leftLimit := (totalWidth-maxIceWidth)/2 - startX
 	rightLimit := totalWidth/2 + maxIceWidth/2 - startX

+ 13 - 4
games/game.go

@@ -6,6 +6,8 @@ import (
 	"encoding/json"
 	"log"
 	"math/rand"
+	"os"
+	"runtime/pprof"
 	"sync"
 	"time"
 
@@ -25,6 +27,13 @@ type Game struct {
 func NewGame(cols, rows int) *Game {
 	createTime := time.Now().Unix()
 
+	f, err := os.Create("cpuprofile.log")
+	if err != nil {
+		log.Fatal(err)
+	}
+	pprof.StartCPUProfile(f)
+	defer pprof.StopCPUProfile()
+
 	game := &Game{
 		StartTime: createTime,
 		Board:     board.NewRemote(cols, rows),
@@ -64,8 +73,8 @@ type updatePlayers struct {
 }
 
 type stompGameEnd struct {
-	Type   string `json:"type"`
-	GameId int64  `json:"gameId"`
+	Type    string `json:"type"`
+	GameId  int64  `json:"gameId"`
 	Payload string `json:"payload"`
 }
 
@@ -109,8 +118,8 @@ func (g *Game) Move(p *player.Player, direction string, sc *stomp.Conn) bool {
 		g.EndTime = time.Now().Unix()
 		g.Winner = p
 		ge := stompGameEnd{
-			Type:   "GAME_END",
-			GameId: g.Id,
+			Type:    "GAME_END",
+			GameId:  g.Id,
 			Payload: g.Winner.Id,
 		}
 		c, _ := json.Marshal(ge)