1
0
mirror of https://github.com/golang/go synced 2024-11-26 17:26:56 -07:00

internal/trace: make Reader output deterministic

Multiple Ms can offer Events with identical timestamps. The Reader
edits those so the timestamps are strictly increasing, but it needs a
way to break the tie. Use something deterministic (such as the order of
the batches), rather than map iteration order.

Updates #68277

Change-Id: I4a1f70c1669ce1c9b52d09e2bc99acbc831ef9a4
Reviewed-on: https://go-review.googlesource.com/c/go/+/596355
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Rhys Hiltner <rhys.hiltner@gmail.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
This commit is contained in:
Rhys Hiltner 2024-07-02 15:26:32 -07:00 committed by Gopher Robot
parent 601ea46a53
commit 1c4acea03d
3 changed files with 44 additions and 2 deletions

View File

@ -25,6 +25,7 @@ import (
type generation struct {
gen uint64
batches map[ThreadID][]batch
batchMs []ThreadID
cpuSamples []cpuSample
*evTable
}
@ -169,6 +170,9 @@ func processBatch(g *generation, b batch) error {
return err
}
default:
if _, ok := g.batches[b.m]; !ok {
g.batchMs = append(g.batchMs, b.m)
}
g.batches[b.m] = append(g.batches[b.m], b)
}
return nil

View File

@ -142,7 +142,8 @@ func (r *Reader) ReadEvent() (e Event, err error) {
r.cpuSamples = r.gen.cpuSamples
// Reset frontier.
for m, batches := range r.gen.batches {
for _, m := range r.gen.batchMs {
batches := r.gen.batches[m]
bc := &batchCursor{m: m}
ok, err := bc.nextEvent(batches, r.gen.freq)
if err != nil {

View File

@ -507,7 +507,7 @@ func TestTraceStress(t *testing.T) {
case "js", "wasip1":
t.Skip("no os.Pipe on " + runtime.GOOS)
}
testTraceProg(t, "stress.go", nil)
testTraceProg(t, "stress.go", checkReaderDeterminism)
}
func TestTraceStressStartStop(t *testing.T) {
@ -535,6 +535,43 @@ func TestTraceIterPull(t *testing.T) {
testTraceProg(t, "iter-pull.go", nil)
}
func checkReaderDeterminism(t *testing.T, tb, _ []byte, _ bool) {
events := func() []trace.Event {
var evs []trace.Event
r, err := trace.NewReader(bytes.NewReader(tb))
if err != nil {
t.Error(err)
}
for {
ev, err := r.ReadEvent()
if err == io.EOF {
break
}
if err != nil {
t.Fatal(err)
}
evs = append(evs, ev)
}
return evs
}
evs1 := events()
evs2 := events()
if l1, l2 := len(evs1), len(evs2); l1 != l2 {
t.Fatalf("re-reading trace gives different event count (%d != %d)", l1, l2)
}
for i, ev1 := range evs1 {
ev2 := evs2[i]
if s1, s2 := ev1.String(), ev2.String(); s1 != s2 {
t.Errorf("re-reading trace gives different event %d:\n%s\n%s\n", i, s1, s2)
break
}
}
}
func testTraceProg(t *testing.T, progName string, extra func(t *testing.T, trace, stderr []byte, stress bool)) {
testenv.MustHaveGoRun(t)