Skip to content

cmd/trace, x/exp/trace: nondeterministic output, seems related to timestamp tie-breaking #68277

@rhysh

Description

@rhysh
$ ~/sdk/go1.23/bin/go version
go version go1.23rc1 darwin/arm64

(This also affects go1.22.4.)

After preparing an execution trace like so ...

$ ~/sdk/go1.23/bin/go test net/http -run='^$' -bench='BenchmarkClientServerParallel/64/h2' -benchtime=100ms -trace=/tmp/trace123_h2

... I read it back with go tool trace -d=1 (and with other tools based on golang.org/x/exp/trace). The results vary each time due to differences in the reported timestamp for some events. The events in question have sequential timestamps, which makes me suspect there's a tie which is getting resolved when reading back the trace, exposing some nondeterminism from map iteration order.

I expected the results of go tool trace -d=1 to be identical each time for a given execution trace. I expected that reading an execution trace with a golang.org/x/exp/trace.Reader and passing each Event to fmt.Print would give identical results on each run. I expected that loading an execution trace twice with golang.org/x/exp/trace.Reader and advancing to a particular timestamp would result in seeing the "same" Event.

CC @golang/runtime @mknyszek

Note that the contents of Events 2 and 3 are swapped between the first and second run, with the timestamps remaining monotonic.

$ ~/sdk/go1.23/bin/go tool trace -d=1 /tmp/trace123_h2 | grep 8653440991110
M=8191703744 P=4 G=-1 StateTransition Time=865344099111040 Resource=Goroutine(20062) Reason="" GoID=20062 Runnable->Running
M=6163394560 P=1 G=21401 StateTransition Time=865344099111041 Resource=Goroutine(28134) Reason="" GoID=28134 Waiting->Runnable
M=6165688320 P=5 G=28541 StateTransition Time=865344099111042 Resource=Goroutine(28541) Reason="select" GoID=28541 Running->Waiting

$ ~/sdk/go1.23/bin/go tool trace -d=1 /tmp/trace123_h2 | grep 8653440991110
M=8191703744 P=4 G=-1 StateTransition Time=865344099111040 Resource=Goroutine(20062) Reason="" GoID=20062 Runnable->Running
M=6165688320 P=5 G=28541 StateTransition Time=865344099111041 Resource=Goroutine(28541) Reason="select" GoID=28541 Running->Waiting
M=6163394560 P=1 G=21401 StateTransition Time=865344099111042 Resource=Goroutine(28134) Reason="" GoID=28134 Waiting->Runnable

With 930k events, several thousand will end up as additional/non-unique lines between two runs of go tool trace -d=1.

$ ~/sdk/go1.23/bin/go tool trace -d=1 /tmp/trace123_h2 | grep '^M=' | wc -l
  930838
$ (~/sdk/go1.23/bin/go tool trace -d=1 /tmp/trace123_h2 ; ~/sdk/go1.23/bin/go tool trace -d=1 /tmp/trace123_h2) | grep '^M=' | sort -u | wc -l
  934396
$ (~/sdk/go1.23/bin/go tool trace -d=1 /tmp/trace123_h2 ; ~/sdk/go1.23/bin/go tool trace -d=1 /tmp/trace123_h2) | grep '^M=' | sort -u | wc -l
  933605
$ (~/sdk/go1.23/bin/go tool trace -d=1 /tmp/trace123_h2 ; ~/sdk/go1.23/bin/go tool trace -d=1 /tmp/trace123_h2) | grep '^M=' | sort -u | wc -l
  938976
$ (~/sdk/go1.23/bin/go tool trace -d=1 /tmp/trace123_h2 ; ~/sdk/go1.23/bin/go tool trace -d=1 /tmp/trace123_h2) | grep '^M=' | sort | uniq -c | awk '{print $1}' | sort | uniq -c
5618 1
928029 2
$ (~/sdk/go1.23/bin/go tool trace -d=1 /tmp/trace123_h2 ; ~/sdk/go1.23/bin/go tool trace -d=1 /tmp/trace123_h2) | grep '^M=' | sort | uniq -c | awk '{print $1}' | sort | uniq -c
4276 1
928700 2
$ (~/sdk/go1.23/bin/go tool trace -d=1 /tmp/trace123_h2 ; ~/sdk/go1.23/bin/go tool trace -d=1 /tmp/trace123_h2) | grep '^M=' | sort | uniq -c | awk '{print $1}' | sort | uniq -c
5630 1
928023 2

Metadata

Metadata

Assignees

No one assigned

    Labels

    FixPendingIssues that have a fix which has not yet been reviewed or submitted.FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.compiler/runtimeIssues related to the Go compiler and/or runtime.

    Type

    No type

    Projects

    Status

    Done

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions