Error when using go tool trace

2,399 views
Skip to first unread message

xavier.ern...@gmail.com

unread,
Oct 11, 2016, 10:21:17 AM10/11/16
to golang-nuts
Hello,
I m trying to use the go tool trace. My code is 


package main

import (
"flag"
"fmt"
"math"
"net/http"
"os"
"runtime"
"runtime/trace"
"time"
)

func indexHandler(w http.ResponseWriter, r *http.Request) {
primesInRangeParallel(10, 64)
fmt.Fprintf(w, "hello world, I'm running on %s with an %s CPU ", runtime.GOOS, runtime.GOARCH)

}

func main() {
flag.Parse()
f, errs := os.Create(time.Now().Format("2006-01-02T150405.out"))
if errs != nil {
panic(errs)
}

if err := trace.Start(f); err != nil {
panic(err)
}

defer f.Close()
defer trace.Stop()
http.HandleFunc("/", indexHandler)

http.ListenAndServe(":8080", nil)
}

// We will use this struct to communicate results via a channel
type PrimeResult struct {
number int64 // A number
prime  bool  // Is prime or not
}

/**
 * A function to return a prime calculation over a channel. This way
 * we don't need to have 2 versions of isPrime function, one for
 * sequential calculations and another for paralel
 */

func isPrimeAsync(number int64, channel chan PrimeResult) {

result := new(PrimeResult)
result.number = number
result.prime = isPrime(number)
channel <- *result
}

/**
 * Accepts a range of integers [min, max] and a channel and it executes
 * in PARALEL the processes that check if a number is prime or not.
 *
 * This function does nothing with the result. In another point, somebody
 * will have to read the channel and process the results
 */
func firePrimeCalculations(min int64, max int64, channel chan PrimeResult) {
var i int64
for i = min; i <= max; i++ {
go isPrimeAsync(i, channel)
}
}

/**
 * Accepts a range of integers [min, max] and
 * returns an array with all the prime numbers in this range.
 *
 * Execution is done in paralel. First it fires all the
 * processes that check for a prime number. These processes
 * will write the result in a channel.
 *
 * We will receive the results over this channel creating the
 * list of prime numbers and returning it
 *
 */

func primesInRangeParallel(min int64, max int64) []int64 {
var primeNumbers []int64
var res PrimeResult
var prev int64

channel := make(chan PrimeResult)
defer close(channel)

go firePrimeCalculations(min, max, channel)

prev = 0
for i := min; i <= max; i++ {
res = <-channel
if res.prime {
primeNumbers = append(primeNumbers, res.number)

done := 100 * (i - min) / (max - min)
if prev != done {
fmt.Printf("%d %% done.\n", done)
prev = done
}
}
}
return primeNumbers
}
func isPrime(candidate int64) bool {
var i, limit int64

if candidate == 2 {
return true
}

if math.Mod(float64(candidate), 2) == 0 {
return false
}

limit = int64(math.Ceil(math.Sqrt(float64(candidate))))
for i = 3; i <= limit; i += 2 { //Only odd numbers
if math.Mod(float64(candidate), float64(i)) == 0 {
return false
}
}
return true
}

The prime number calculation is basically there to get some calculation.

My go env command gives  : 

C:\repo\gonew\src\github.com\tixu\trace>go env
set GOARCH=amd64
set GOBIN=
set GOEXE=.exe
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=windows
set GOPATH=c:\repo\gonew
set GORACE=
set GOROOT=C:\Go
set GOTOOLDIR=C:\Go\pkg\tool\windows_amd64
set CC=gcc
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0
set CXX=g++
set CGO_ENABLED=1


And I get the following error :

C:\repo\gonew\src\github.com\tixu\trace>go tool trace Trace 2016-10-11T153554.out
2016/10/11 15:36:45 Parsing trace...
failed to parse trace: no EvFrequency event 

Can you help me .?

Thanks in advance,

Xavier

ma...@influxdb.com

unread,
Nov 3, 2016, 12:33:15 AM11/3/16
to golang-nuts


On Tuesday, October 11, 2016 at 7:21:17 AM UTC-7, xavier zebier wrote:
C:\repo\gonew\src\github.com\tixu\trace>go tool trace Trace 2016-10-11T153554.out
2016/10/11 15:36:45 Parsing trace...
failed to parse trace: no EvFrequency event 

Can you help me .?

Thanks in advance,

Xavier

I ran into the same error. AFAICT that error means your trace file is missing a footer.

The code in this playground link[1] starts a TCP server on port 9999.

If you run (sleep 5; echo "ok") | nc localhost 9999 > out.trace
you'll correctly read an entire trace file which will open successfully with go tool trace.

OTOH if you just run nc localhost 9999 > out.trace and then hit ctrl-c,
you'll see the "no EvFrequency event" error when you visit (most of) the routes
from go tool trace's server.

evan.e...@gmail.com

unread,
Aug 4, 2017, 1:46:39 AM8/4/17
to golang-nuts
I ran into this same problem, and found this post!
It looks like you're making the same simple mistake I was:

# erroneous:
defer f.Close()
defer trace.Stop()

You must stop the trace before closing the output file.

# corrected:
defer func() {
  trace.Stop()
  panic(f.Close()) # Be sure to handle file-closing errors. They're important!!

Dave Cheney

unread,
Aug 4, 2017, 2:42:31 AM8/4/17
to golang-nuts


On Friday, 4 August 2017 15:46:39 UTC+10, Evan Leis wrote:
I ran into this same problem, and found this post!
It looks like you're making the same simple mistake I was:

# erroneous:
defer f.Close()
defer trace.Stop()

Defers run in LIFO order. This sample will call trace.Stop, then f.Close(). 

You must stop the trace before closing the output file.

# corrected:
defer func() {
  trace.Stop()
  panic(f.Close()) # Be sure to handle file-closing errors. They're important!!
}

This sample will panic the program every time 

evan.e...@gmail.com

unread,
Aug 4, 2017, 8:33:34 PM8/4/17
to golang-nuts
Ah, excellent. Good catch. I learned something about defer.

The ordering of the close was my problem, however. 
The way I *actually* handle closing the trace is:

func (t *FileTracer) Stop() error {
if t == nil {
return nil
}
trace.Stop()
return t.f.Close()
Reply all
Reply to author
Forward
0 new messages