added stats server option to debug and play mode

package from https://github.com/go-echarts/statsview
This commit is contained in:
JetSetIlly 2020-11-21 18:44:12 +00:00
parent 8d85624023
commit 3880066322
5 changed files with 123 additions and 1 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

View file

@ -24,6 +24,65 @@ The graphical [debugger](#debugger) is still in development but the current feat
<img src=".screenshots/games/krull.png" height="200" alt="krull"/> <img src=".screenshots/games/ladybug.png" height="200" alt="ladybug"/>
<img src=".screenshots/games/thrust.png" height="200" alt="thrust"/> <img src=".screenshots/games/pandachase.png" height="200" alt="panda chase"/> <img src=".screenshots/games/mangoesdown.png" height="200" alt="man goes down"/> <img src=".screenshots/games/beast.png" height="200" alt="legacy of the beast"/> <img src=".screenshots/games/chiphead.png" height="200" alt="chiphead"/> <img src=".screenshots/games/genesis.png" height="200" alt="egypt genesis"/>
## Scope of the project
`Gopher2600` was started as for fun and educational purposes, as way of
learning more about the `Atari 2600` and also about the
[Go programming language](https://golang.org/).
The original intent was to provide a tool for static analysis of a 6507
program. I soon realised that I would need to emulate more and more of the
2600 and not just the CPU. Eventually, I realised I would also need a way of see the
video output from the TIA. At this point it became obvious that I was indeed
writing a complete 2600 emulator.
Because of its origins, any flaws or limitations in the design should be borne
in mind while the project is still in development. I am open to any suggestions
on how to improve the project.
### Self-reflection
There are some design decisions that would perhaps be made differently if I had
known where the program was going. For instance, because the project was a way
of learning a new programming language I chose to implement my own "database"
to [store regression test information](#regression-database). A more natural
choice would be to use SQlite but actually the current solution works quite
well.
A couple of packages may well be useful in other projects. The `prefs` package
is quite versatile. With a bit of work it could be generalised and put to use
in other projects. I think though, this package is a natural candidate to be
rewritten with type parameters. Not yet available in Go but scheduled for
release in 2022.
I would also replace the `commandline` package. It works quite nicely but as
you would expect from a home-baked solution there are limitations to the
parser. It should be rewritten with `flex` & `yacc`.
### Performance
The development machine for `Gopher2600` was an i3-3225 with 16GB of RAM. Host
operating system throughout the development has been a GNU/Linux system.
In playmode I can get a sustained frame rate of 60fps. However, video output is
not properly vsynced and the audio buffer is not handled very well, sometimes
running out of bits, resulting in pops and stutters in the sound.
In debug mode, I can get around 35fps - good enough for development work.
To get a performance rating for your installation you can run the following:
> gopher2600 performance -display -fpscap=false
Which gives the maximum frame rate with the display.
Memory usage is around 40MB of system memory in playmode and around 120MB in
debug mode. This can vary on the ROM used however. It shouldn't ever be a
problem on modern hardware.
A `statsview` is also available. See the section below on [Statistics Viewer](#statistics-viewer) for
details.
## Compilation
The project has most recently been tested with Go v1.15. Earlier versions may work
@ -407,7 +466,7 @@ This area of the emulation will be expanded upon in the future.
* M-Network (E7)
* DPC
In also supports the `Supercharger` format in both the `.bin` format and is also able to load from an `MP3` recording of the supercharger tape.
In also supports the [Supercharger](#supercharger-roms) format in both the `.bin` format and is also able to load from an `MP3` recording of the supercharger tape.
Modern formats supported:
@ -418,6 +477,25 @@ Modern formats supported:
The `DPC+` is supported but the emulator does not currently emulate the `ARM7` present in the `Harmony` cartridge. This is planned for the future.
## Statistics Viewer
Playmode and debug mode can both be launched with a statistics viewer available
locally on your machine `localhost:12600/debug/statsview`.
> gopher2600 -statsserver <rom>
> gopher2600 debug -statsserver <rom>
The screen below shows an example of the available statistics. In this
instance, this is the debugger running a 4k Atari cartridge (specifically,
Pitfall).
<img src=".screenshots/statsserver_debug.png" width="600" alt="stats server example charts (for the debugger)"/>
For people who really want to dig deep into the running program,
`localhost:12600/debug/pprof/` gives more raw, but still useful
information.
## Gopher2600 Tools
See the https://github.com/JetSetIlly/Gopher2600-Utils/ repository for examples of tools
@ -500,6 +578,10 @@ The following projects are used in the `Gopher2600` project:
* https://github.com/hajimehoshi/go-mp3
* https://github.com/pkg/term
Stats server provided by:
* https://github.com/go-echarts/statsview
For testing instrumentation:
* https://github.com/bradleyjkemp/memviz v0.2.3

1
go.mod
View file

@ -7,6 +7,7 @@ go 1.15
//replace github.com/inkyblackness/imgui-go/v2 v2.5.0 => /home/steve/Go/steve_forks/imgui-go
require (
github.com/go-echarts/statsview v0.3.0
github.com/bradleyjkemp/memviz v0.2.3
github.com/go-audio/audio v1.0.0
github.com/go-audio/wav v1.0.0

13
go.sum
View file

@ -15,6 +15,10 @@ github.com/go-audio/riff v1.0.0 h1:d8iCGbDvox9BfLagY94fBynxSPHO80LmZCaOsmKxokA=
github.com/go-audio/riff v1.0.0/go.mod h1:l3cQwc85y79NQFCRB7TiPoNiaijp6q8Z0Uv38rVG498=
github.com/go-audio/wav v1.0.0 h1:WdSGLhtyud6bof6XHL28xKeCQRzCV06pOFo3LZsFdyE=
github.com/go-audio/wav v1.0.0/go.mod h1:3yoReyQOsiARkvPl3ERCi8JFjihzG6WhjYpZCf5zAWE=
github.com/go-echarts/go-echarts/v2 v2.2.2 h1:GRx69WvDwbXkYW11Z5JaDLEkUwypqcLyms8A8n1JWC0=
github.com/go-echarts/go-echarts/v2 v2.2.2/go.mod h1:6TOomEztzGDVDkOSCFBq3ed7xOYfbOqhaBzD0YV771A=
github.com/go-echarts/statsview v0.3.0 h1:RTa3DjHnBP2rH2wk8/1HZH71NjznAeVF5dSU/0tZtEg=
github.com/go-echarts/statsview v0.3.0/go.mod h1:MVu0ODAoc/gwQ4wv09+Ev+4O2GghebSMN0vk1WkHTe8=
github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 h1:SCYMcCJ89LjRGwEa0tRluNRiMjZHalQZrVrvTbPh+qw=
github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7/go.mod h1:482civXOzJJCPzJ4ZOX/pwvXBWSnzD4OKMdH4ClKGbk=
github.com/hajimehoshi/go-mp3 v0.3.1 h1:pn/SKU1+/rfK8KaZXdGEC2G/KCB2aLRjbTCrwKcokao=
@ -30,13 +34,19 @@ github.com/inkyblackness/imgui-go/v2 v2.5.0 h1:kz7oO/di/TmxHKgh5So+RyOgWMtK4jLfG
github.com/inkyblackness/imgui-go/v2 v2.5.0/go.mod h1:cwQKd6U2onyuT5qwSC3DKCRsUE1SQ58TSVVpLoW/pDs=
github.com/inkyblackness/imgui-go/v2 v2.5.1-0.20200909052151-c2b62c6be2a7 h1:rYHbANjC8SF9JP7n85+f9tgUm8Akvdc7wUhLDA0Whj4=
github.com/inkyblackness/imgui-go/v2 v2.5.1-0.20200909052151-c2b62c6be2a7/go.mod h1:cwQKd6U2onyuT5qwSC3DKCRsUE1SQ58TSVVpLoW/pDs=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/pkg/term v0.0.0-20190109203006-aa71e9d9e942 h1:A7GG7zcGjl3jqAqGPmcNjd/D9hzL95SuoOQAaFNdLU0=
github.com/pkg/term v0.0.0-20190109203006-aa71e9d9e942/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/veandco/go-sdl2 v0.4.1 h1:HmSBvVmKWI8LAOeCfTTM8R33rMyPcs6U3o8n325c9Qg=
github.com/veandco/go-sdl2 v0.4.1/go.mod h1:FB+kTpX9YTE+urhYiClnRzpOXbiWgaU3+5F2AB78DPg=
github.com/veandco/go-sdl2 v0.4.4 h1:coOJGftOdvNvGoUIZmm4XD+ZRQF4mg9ZVHmH3/42zFQ=
@ -47,3 +57,6 @@ golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCc
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View file

@ -24,6 +24,8 @@ import (
"strings"
"time"
"github.com/go-echarts/statsview"
"github.com/go-echarts/statsview/viewer"
"github.com/jetsetilly/gopher2600/cartridgeloader"
"github.com/jetsetilly/gopher2600/debugger"
"github.com/jetsetilly/gopher2600/debugger/terminal"
@ -270,6 +272,7 @@ func play(md *modalflag.Modes, sync *mainSync) error {
hiscore := md.AddBool("hiscore", false, "contact hiscore server [EXPERIMENTAL]")
log := md.AddBool("log", false, "echo debugging log to stdout")
useSavekey := md.AddBool("savekey", false, "use savekey in player 1 port")
statsServer := md.AddBool("statsserver", false, fmt.Sprintf("run stats server (%s)", statsServerAddress))
p, err := md.Parse()
if err != nil || p != modalflag.ParseContinue {
@ -283,6 +286,10 @@ func play(md *modalflag.Modes, sync *mainSync) error {
logger.SetEcho(nil)
}
if *statsServer {
launchStatsServer()
}
switch len(md.RemainingArgs()) {
case 0:
return fmt.Errorf("2600 cartridge required for %s mode", md)
@ -382,12 +389,17 @@ func debug(md *modalflag.Modes, sync *mainSync) error {
initScript := md.AddString("initscript", defInitScript, "script to run on debugger start")
profile := md.AddBool("profile", false, "run debugger through cpu profiler")
useSavekey := md.AddBool("savekey", false, "use savekey in player 1 port")
statsServer := md.AddBool("statsserver", false, fmt.Sprintf("run stats server (%s)", statsServerAddress))
p, err := md.Parse()
if err != nil || p != modalflag.ParseContinue {
return err
}
if *statsServer {
launchStatsServer()
}
tv, err := television.NewTelevision(*spec)
if err != nil {
return err
@ -889,3 +901,17 @@ type nopWriter struct{}
func (*nopWriter) Write(p []byte) (n int, err error) {
return 0, nil
}
const statsServerAddress = "localhost:12600"
const statsServerURL = "/debug/statsview"
// launch a goroutine running the stats viewer https://github.com/go-echarts/statsview
func launchStatsServer() {
go func() {
viewer.SetConfiguration(viewer.WithAddr(statsServerAddress))
mgr := statsview.New()
mgr.Start()
}()
fmt.Printf("stats server available at %s%s\n", statsServerAddress, statsServerURL)
}