perf: display optimization
This commit is contained in:
parent
3d57868e9d
commit
11781c0789
@ -1,18 +1,43 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
"gol/gol"
|
"gol/gol"
|
||||||
"gol/term"
|
"gol/term"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"runtime/pprof"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
cpuprofile := flag.String("cpuprofile", "", "write cpu profile to file")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
// Jeśli podano flagę cpuprofile, rozpocznij profilowanie
|
||||||
|
if *cpuprofile != "" {
|
||||||
|
f, err := os.Create(*cpuprofile)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("could not create CPU profile: ", err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
if err := pprof.StartCPUProfile(f); err != nil {
|
||||||
|
log.Fatal("could not start CPU profile: ", err)
|
||||||
|
}
|
||||||
|
defer pprof.StopCPUProfile()
|
||||||
|
}
|
||||||
|
game()
|
||||||
|
}
|
||||||
|
|
||||||
|
func game() {
|
||||||
|
// arenas - front one is printent, then new state is calculated into back one
|
||||||
|
// next front and back are switched
|
||||||
front := gol.New(20, 40)
|
front := gol.New(20, 40)
|
||||||
back := gol.New(20, 40)
|
back := gol.New(20, 40)
|
||||||
|
|
||||||
|
// draw initial objects
|
||||||
// glider
|
// glider
|
||||||
front[0][3] = true
|
front[0][3] = true
|
||||||
front[1][4] = true
|
front[1][4] = true
|
||||||
@ -21,35 +46,40 @@ func main() {
|
|||||||
front[2][4] = true
|
front[2][4] = true
|
||||||
|
|
||||||
// cross
|
// cross
|
||||||
|
|
||||||
front[16][21] = true
|
front[16][21] = true
|
||||||
front[17][21] = true
|
front[17][21] = true
|
||||||
front[18][21] = true
|
front[18][21] = true
|
||||||
|
|
||||||
|
// catch interrupt signals
|
||||||
sigs := make(chan os.Signal, 1)
|
sigs := make(chan os.Signal, 1)
|
||||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
|
||||||
|
|
||||||
|
// initialize screen
|
||||||
term.StartFullscreen()
|
term.StartFullscreen()
|
||||||
term.TurnCursor(term.CursorOff)
|
term.TurnCursor(term.CursorOff)
|
||||||
|
|
||||||
loop := func() {
|
defer restoreScreen()
|
||||||
ticker := time.NewTicker(250 * time.Millisecond)
|
|
||||||
defer ticker.Stop()
|
// setup timer
|
||||||
for {
|
ticker := time.NewTicker(250 * time.Millisecond)
|
||||||
term.GoHome()
|
defer ticker.Stop()
|
||||||
front.PrintMe()
|
|
||||||
front.NextGen(back)
|
mainLoop:
|
||||||
front, back = back, front
|
for {
|
||||||
select {
|
term.GoHome()
|
||||||
case <-sigs: // przerwanie
|
front.PrintMe()
|
||||||
return
|
front.NextGen(back)
|
||||||
case <-ticker.C: // upłynął czas do kolejnej generacji
|
front, back = back, front // switch arenas
|
||||||
}
|
select {
|
||||||
|
case <-sigs: // interrupt (Ctrl-C etc)
|
||||||
|
break mainLoop
|
||||||
|
case <-ticker.C: // wait for next tick
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
defer func() {
|
}
|
||||||
term.FinishFullscreen()
|
|
||||||
term.TurnCursor(term.CursorOn)
|
// restoreScreen switch back terminal to normal mode.
|
||||||
}()
|
func restoreScreen() {
|
||||||
loop()
|
term.FinishFullscreen()
|
||||||
|
term.TurnCursor(term.CursorOn)
|
||||||
}
|
}
|
||||||
|
27
gol/types.go
27
gol/types.go
@ -1,6 +1,10 @@
|
|||||||
package gol
|
package gol
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"bytes"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
type Arena [][]bool
|
type Arena [][]bool
|
||||||
|
|
||||||
@ -12,18 +16,31 @@ func New(ysize, xsize int) Arena {
|
|||||||
return arena
|
return arena
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bufPool
|
||||||
|
var bufPool = sync.Pool{
|
||||||
|
New: func() any {
|
||||||
|
return new(bytes.Buffer)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
func (a Arena) PrintMe() {
|
func (a Arena) PrintMe() {
|
||||||
|
b := bufPool.Get().(*bytes.Buffer)
|
||||||
|
b.Reset()
|
||||||
|
spriteOn := ([]byte)("\ue0b6\ue0b4")
|
||||||
|
spriteOff := ([]byte)("\u2022\u2022")
|
||||||
|
|
||||||
for i := 0; i < len(a); i++ {
|
for i := 0; i < len(a); i++ {
|
||||||
for j := 0; j < len(a[0]); j++ {
|
for j := 0; j < len(a[0]); j++ {
|
||||||
if a[i][j] {
|
if a[i][j] {
|
||||||
fmt.Print("\ue0b6\ue0b4")
|
b.Write(spriteOn)
|
||||||
} else {
|
} else {
|
||||||
//fmt.Print("\ue0b7\ue0b5")
|
b.Write(spriteOff)
|
||||||
fmt.Print("\u2022\u2022")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Println()
|
b.WriteRune('\n')
|
||||||
}
|
}
|
||||||
|
os.Stdout.Write(b.Bytes())
|
||||||
|
bufPool.Put(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a Arena) NextGen(to Arena) {
|
func (a Arena) NextGen(to Arena) {
|
||||||
|
23
term/term.go
23
term/term.go
@ -13,47 +13,48 @@ const (
|
|||||||
|
|
||||||
// TurnCursor turns the cursor on and off according to the parameter.
|
// TurnCursor turns the cursor on and off according to the parameter.
|
||||||
func TurnCursor(onOff CursorFlag) {
|
func TurnCursor(onOff CursorFlag) {
|
||||||
if onOff == CursorOn {
|
switch onOff {
|
||||||
fmt.Printf("\033[?25h")
|
case CursorOn:
|
||||||
} else {
|
fmt.Print("\033[?25h")
|
||||||
fmt.Printf("\033[?25l")
|
case CursorOff:
|
||||||
|
fmt.Print("\033[?25l")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearScreen clears current screen.
|
// ClearScreen clears current screen.
|
||||||
func ClearScreen() {
|
func ClearScreen() {
|
||||||
fmt.Printf("\033[2J")
|
fmt.Print("\033[2J")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResetTerminal resets terminal (ESC c)
|
// ResetTerminal resets terminal (ESC c)
|
||||||
func ResetTerminal() {
|
func ResetTerminal() {
|
||||||
fmt.Printf("\033c")
|
fmt.Print("\033c")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GoHome moves cursor to the home position (upper left corner)
|
// GoHome moves cursor to the home position (upper left corner)
|
||||||
func GoHome() {
|
func GoHome() {
|
||||||
fmt.Printf("\033[H")
|
fmt.Print("\033[H")
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveCursor saves curent position of the SaveCursor
|
// SaveCursor saves curent position of the SaveCursor
|
||||||
func SaveCursor() {
|
func SaveCursor() {
|
||||||
fmt.Printf("\033[s")
|
fmt.Print("\033[s")
|
||||||
}
|
}
|
||||||
|
|
||||||
// RestoreCursor restore cursor to the position saved previously with SaveCursor().
|
// RestoreCursor restore cursor to the position saved previously with SaveCursor().
|
||||||
func RestoreCursor() {
|
func RestoreCursor() {
|
||||||
fmt.Printf("\033[u")
|
fmt.Print("\033[u")
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnableAlternateScreen switches the terminal to the alternative screen.
|
// EnableAlternateScreen switches the terminal to the alternative screen.
|
||||||
// The alternative screen doesn't have the scroll buffer.
|
// The alternative screen doesn't have the scroll buffer.
|
||||||
func EnableAlternateScreen() {
|
func EnableAlternateScreen() {
|
||||||
fmt.Printf("\033[?1049h")
|
fmt.Print("\033[?1049h")
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiableAlternateScreen switches the terminal to the primary screen.
|
// DiableAlternateScreen switches the terminal to the primary screen.
|
||||||
func DisableAlternateScreen() {
|
func DisableAlternateScreen() {
|
||||||
fmt.Printf("\033[?1049l")
|
fmt.Print("\033[?1049l")
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartFullscreen saves the cursor, enables alternate screen and clears it.
|
// StartFullscreen saves the cursor, enables alternate screen and clears it.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user