Code Monkey home page Code Monkey logo

gotrace's Introduction

GoTrace - Go Concurrency 3D Tracer

GoTrace is a 3D WebGL visualizer of Go concurrency. It analyzes trace produced by go tool trace and renders visualization of concurrency flow.

Original article: https://divan.github.io/posts/go_concurrency_visualize/

Slides from GopherCon'16: http://divan.github.io/talks/2016/gophercon/

Intro

This tool generates 3D visualization of Go concurrency flow by analyzing its execution trace. To view the visualization you need a modern browser with WebGL support (pretty much any browser nowadays).

Its primary goal is to be an educational tool for Go concurrency. It works well with small programs that produce short traces (see Scale issues below).

Usage

First, install gotrace:

go get -u github.com/divan/gotrace

Second, use patched Go runtime to produce trace and binary. There are two ways to do it - use a docker container or apply the patch locally.

Quick example using pre-made docker image (jump to detailed instructions):

docker run --rm -it \
	-e GOOS=darwin \
	-v $(pwd):/src divan/golang:gotrace \
		go build -o /src/binary /src/examples/hello.go
./binary 2> trace.out
gotrace ./trace.out ./binary

Or, using local patched Go installation (jump to detailed instructions):

gotrace examples/hello.go

Prepare your program

Now, please learn some important things before trying your own code. Feel free to play first with code in examples/ folder.

Theoretically, gotrace should do all the magic itself and be able to handle any Go program. That's the goal, but at the present moment, if you want to get good/meaningful visualization, you should follow some rules and suggestions.

Make it short

The height of program visualization currently is a fixed value, so any trace fits into the screen height. This means, that example running 1 minute will be visualized at different scale from program running 1 second.

Depending on what you try to see, but rule of thumb is - the shorter execution time, the better. See examples/ dir for good samples that produce nice visualizations.

Insert runtime/trace yourself

In order to produce the trace, your program should be instrumented with special code. gotrace can do this automatically for you, but in some cases it's wiser to put this code by yourself. Here is a typical example:

package main

import (
	"os"
	"runtime/trace"
)

func main() {
	trace.Start(os.Stderr)
	...
	trace.Stop()
}

Currently it's important to write trace into os.Stderr. See issue #X if your example uses stderr for other needs.

Consider inserting very short time.Sleep() calls

If you are trying to visualize some things that happen at nanosecond/microsecond level, it could be wise to insert time.Sleep(1 * time.Millisecond) calls to get more clear visualization.

For example, if your code runs 100 goroutines in a loop, their IDs and their start order probably would be different, resulting in slightly messed picture. So, changing:

	for i := 0; i < 100; i++ {
		go player(table)
	}

to

	for i := 0; i < 100; i++ {
		time.Sleep(1 * time.Millisecond)
		go player(table)
	}

will help to make better visualization.

Try to keep number of goroutines/events small

The fewer objects that will be rendered, the better. If you have many things to render, WebGL will just hang your browser. Also, keep in mind, that point of visualization is to express something. So running 1024 workers will result in a heavy visualization where you will not see separate goroutines. Setting this value to, say, 36 will produce much more clear picture.

Detailed instructions

The next step is to build your program. You will need to build using the patched Go runtime. So if you patched it yourself (see Appendix A), you just have to run go build, or, even simpler, let gotrace do it for you. But most people, probably wouldn't want to do this and prefer using Docker for it.

Using Docker

You will need Docker installed and running.

Then pull the image from Docker Hub:

docker pull divan/golang:gotrace

or build it yourself:

docker build -t "divan/golang:gotrace" -f runtime/Dockerfile runtime/

If everything went ok, you should have divan/golang:gotrace image in your local docker (check with docker images command).

Now, use this command to produce the binary:

MacOS X
docker run --rm -it \
	-e GOOS=darwin \
	-v $(pwd):/src divan/golang:gotrace \
		go build -o /src/binary /src/examples/hello.go
Linux
docker run --rm -it \
	-v $(pwd):/src divan/golang:gotrace \
		go build -o /src/binary /src/examples/hello.go
Windows
docker run --rm -it \
	-e GOOS=windows \
	-v $(pwd):/src divan/golang:gotrace \
		go build -o /src/binary.exe /src/examples/hello.go

3. Run it and save the trace.

Once you have the binary, you can run it and save the trace:

./binary 2> trace.out

4. Run gotrace (finally)

Now, it's time to run gotrace and feed the binary and the trace to produce the visualization:

gotrace ./trace.out ./binary

It should start the browser and render visualization.

Visualization

Colors

Different colors of goroutines represent different states.

  • red - blocked state
  • green - unblocked
  • yellow - unblocked and using CPU

Colors of goroutines' connections and sendings over the channels are the same.

Hotkeys

You can use the mouse/trackpad to zoom/rotate/pan visualization. On MacOS X you use single tap and move to rotate, double-finger touch to zoom, and double-finger tap and move to pan.

You may also try it with a Leap Motion controller for zooming and rotating with hands - switch to leap branch.

Also there are some useful hotkeys:

  • r - restart
  • p - pause
  • 1, 2, 3, 4, 0 - highlight modes (0 - default)
  • +/- - increase/decrease width of lines
  • s/f - slower/faster animation

Limits/Known issues

  • Value of variable being sent to the channel is supported only for integer types. (see Issue #3)
  • Buffered channels doesn't work (yet) (see Issue #2)

Appendix A - patching Go locally

If you really want to play around with gotrace, you may want to patch Go runtime yourself. It will allow you to run gotrace as easy as gotrace main.go without all intermediate steps described above.

Here are instructions on how to do it (MacOS X and Linux).

  1. Assuming your Go installation is in /usr/local/go (default), download Go 1.6.3 and unpack it into /usr/local/go163.

     sudo -i
     mkdir -p /usr/local/go163
     curl https://storage.googleapis.com/golang/go1.6.3.src.tar.gz | tar -xz -C /usr/local/go163
    
  2. Then, copy patch and apply it:

     sudo patch -p1 -d /usr/local/go163/go < runtime/go1.6.3-tracenew.patch
    
  3. Build new runtime:

     sudo -i
     cd /usr/local/go163/go/src
     export GOROOT_BOOTSTRAP=/usr/local/go # or choose yours
     ./make.bash
    
  4. Finally, export PATH or use ln -s command to make this Go version actual in your system:

     export PATH=/usr/local/go163/go/bin:$PATH
    

or (assuming your PATH set to use /usr/local/go)

	sudo mv /usr/local/go /usr/local/go-orig
	sudo ln -nsf /usr/local/go163/go /usr/local/go

NOTE: return your previous installation by sudo ln -nsf /usr/local/go-orig /usr/local/go

Now, you should be able to run gotrace main.go and get the result.

License

MIT License

gotrace's People

Contributors

divan avatar kevinburke avatar zchee avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gotrace's Issues

Can't figure out how to build more complex examples

The example using docker to build works for simple hello.go, but I can't figure out the syntax for a more complex example. I'm just not familiar enough with go and docker to figure this out, sorry.

Could you extend the documentation to give a more general example?

Thanks

$ docker run --rm -it \
>     -e GOOS=darwin \
>     -v $(pwd):/src divan/golang:gotrace \
>         go build -o /src/spigo-gotrace /src/spigo.go
/src/spigo.go:7:2: cannot find package "github.com/adrianco/spigo/actors/edda" in any of:
    /usr/local/go/src/github.com/adrianco/spigo/actors/edda (from $GOROOT)
    /go/src/github.com/adrianco/spigo/actors/edda (from $GOPATH)
... and many more similar errors

Upstreaming channel send/recv events

This is a very useful feature. Was there any effort to upstream the runtime changes to upstream? It would greatly help to see the channel send/receive events in traces. Currently, channel events under the select statement do not appear in traces and using channels in select cases is very common.

trace.Parse error in go1.8.1

I followed the advice given in this issue

But get the following error when trying to install the package:
./events.go:50: too many arguments in call to trace.Parse have (io.Reader, string) want (io.Reader)

When i attempt to do the same within the docker image provided in this repo,I also get the same error.

Any advice would be greatly appreciated,
Thanks

tracing across multiple go files

just ran your code on a modified version of our master and it worked but is less detailed than we would like
animation_shot
.

Our worker code is in a separate go file. Is it possible add traces into the worker go files and capture all the go routine actions in one animation?

Listing in awesome-go list?

I created PR to get gotrace listed on https://awesome-go.com/. But there is meta-data about the project (code coverage, etc.) missing which is probably not reasonable. Anyway... probably it's reasonable to re-open the PR to get this nice tool added.

Fails to pass tests (master and go18)

~/g/s/g/d/gotrace (go18|✔) ❯❯❯ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
~/g/s/g/d/gotrace (master|✔) ❯❯❯ go test
open /home/dexter/go/src/github.com/divan/gotrace/examples/hello01.go: no such file or directory
--- FAIL: TestExamples (0.00s)
        main_test.go:30: Testing examples/hello01.go
        main_test.go:34: examples/hello01.go couldn't rewrite source code: couldn't load packages due to errors: (unnamed)
FAIL
exit status 1
FAIL    github.com/divan/gotrace        0.004s
~/g/s/g/d/gotrace (master|✔) ❯❯❯ go build
~/g/s/g/d/gotrace (master|✔) ❯❯❯ go test
open /home/dexter/go/src/github.com/divan/gotrace/examples/hello01.go: no such file or directory
--- FAIL: TestExamples (0.00s)
        main_test.go:30: Testing examples/hello01.go
        main_test.go:34: examples/hello01.go couldn't rewrite source code: couldn't load packages due to errors: (unnamed)
FAIL
exit status 1
FAIL    github.com/divan/gotrace    

Not a trace file error

Hi,

I followed the steps as mentioned in the README, I got no errors at all when doing the instructions for docker pull and docker run. I can see the binary file and the trace.out file. However, when I run the gotrace ./trace.out ./binary command, this error: panic: not a trace file goroutine 1 [running]: main.main() /Users/jeffreyyong/go/src/github.com/divan/gotrace/main.go:39 +0x3d2 occurred. It's strange, because I'm supposed to build /src/examples/hello.go but the error occurs in main.go

I am running it on MacOs. I am wondering if I have to set other environment variable like GOARCH when doing docker run?

Regards,
Jeffrey

Recognize goroutines' patterns for proper visualization

In many cases goroutines' invocation have some patterns (i.e. workers, server, etc). They could (and should) be grouped logically and visually separated from other goroutines/groups. This goal is achieved by customizing visualization properties like "angle" and "distance".

Currently the following scheme is implemented: for each goroutine the nesting depth is calculated (0 - means 'main', 1 - 'started from main', etc). Then angle for this depth level is calculated as simple as 360/count.

This approach is ok for simple 1 or 2 nesting level programs (TODO: analyze all github projects to see distribution of goroutines nesting). For more complex programs the visualization will be probably messy.

Workaround: allow user to configure angles/distances manually (per goroutine name, maybe?)

Proper solution: detect patterns, based on name+parent+creation_time and calculate angles/distances separately for each pattern group.

Does not works use gb

I tried gotrace's patch(runtime/go1.6.3-tracenew.patch) with gb.
But when gb build, does not proceed(freeze).

Here is repro way.

curl https://storage.googleapis.com/golang/go1.6.3.src.tar.gz | tar -xz -C /usr/local/go163
patch -p1 -d /usr/local/go163 < runtime/go1.6.3-tracenew.patch
cd /usr/local/go163/src
export GOROOT_BOOTSTRAP=/path/to/go1.4.3
./make.bash
export PATH=/usr/local/go163/bin:$PATH

# gb use build.Default, re-build gb binary
go get -u -v -x github.com/constabulary/gb/...
cd /path/to/tmp
git clone https://github.com/constabulary/example-gsftp gsftp
cd gsftp

gb env
  GB_PROJECT_DIR="/Users/zchee/go/src/github.com/constabulary/gsftp"
  GB_SRC_PATH="/Users/zchee/go/src/github.com/constabulary/gsftp/src:/Users/zchee/go/src/github.com/constabulary/gsftp/vendor/src"
  GB_PKG_DIR="/Users/zchee/go/src/github.com/constabulary/gsftp/pkg/darwin-amd64"
  GB_BIN_SUFFIX="-darwin-amd64"
  GB_GOROOT="/usr/local/go-trace"

gb vendor restore
gb build

gb has not -v flag for build command.
Now I'm trying another debug way.

Thanks.

Add support for buffered channels

Currently only unbuffered channels are supported. Buffered channels send/recv will not appear in visualization made by gotrace.

That's because buffered and unbuffered channels implemented differently, and in the first case there is no (obvious) way to attach something like EventID for sending/receiving event, which is needed to correlate send/recv events.
More details to come.

cap() returns always 0

I am not sure why this is happening, as I haven't digged deeper, however a call to cap() always returns 0.

This makes a lot of code just hang and breaks badly.

Add support for go1.9

gotrace$ gotrace ./trace.out
panic: unsupported trace file version 1.9 (update Go toolchain) 1009

goroutine 1 [running]:
main.main()
/mnt/e/go/src/github.com/divan/gotrace/main.go:35 +0x2c8

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.