From 23cca8864a100a89cda5dcd3e0e8bbe7e973e09f Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Fri, 24 May 2024 20:32:24 +0000 Subject: [PATCH] trace: regenerate trace from go@b89f946 [git-generate] cd trace ./gen.bash $HOME/work/go Change-Id: I8cd13461f1ecec0790f682343a7a9f7e8766be0f Reviewed-on: https://go-review.googlesource.com/c/exp/+/588140 Reviewed-by: Michael Pratt LUCI-TryBot-Result: Go LUCI Auto-Submit: Michael Knyszek --- trace/base.go | 6 +- trace/batch.go | 26 +++- trace/batchcursor.go | 2 +- trace/batchcursor_test.go | 2 +- trace/cmd/gotraceeventstats/main.go | 140 ++++++++++++++++++ trace/cmd/gotraceraw/main.go | 2 +- trace/cmd/gotracevalidate/main.go | 2 +- trace/event.go | 75 +++++++++- trace/event_test.go | 2 +- trace/generation.go | 36 ++++- trace/internal/event/event.go | 33 +++-- trace/internal/event/go122/event.go | 97 +++++++++++- trace/internal/event/requirements.go | 2 +- trace/internal/oldtrace/order.go | 16 +- trace/internal/oldtrace/parser.go | 10 +- trace/internal/raw/doc.go | 2 +- trace/internal/raw/event.go | 2 +- trace/internal/raw/reader.go | 2 +- trace/internal/raw/textreader.go | 2 +- trace/internal/raw/textwriter.go | 2 +- trace/internal/raw/writer.go | 2 +- trace/internal/testgen/go122/trace.go | 2 +- trace/internal/testtrace/expectation.go | 2 +- trace/internal/testtrace/format.go | 2 +- trace/internal/testtrace/validation.go | 2 +- trace/internal/version/version.go | 2 +- trace/oldtrace.go | 2 +- trace/order.go | 30 +++- trace/order_test.go | 2 +- trace/parser.go | 83 +++++++++++ trace/reader.go | 10 +- trace/reader_test.go | 2 +- trace/resources.go | 2 +- trace/testdata/generate.go | 2 +- .../go122-confuse-seq-across-generations.go | 2 +- .../go122-create-syscall-reuse-thread-id.go | 2 +- .../generators/go122-create-syscall-with-p.go | 2 +- .../generators/go122-fail-first-gen-first.go | 48 ++++++ .../go122-go-create-without-running-g.go | 2 +- .../go122-syscall-steal-proc-ambiguous.go | 2 +- ...-syscall-steal-proc-gen-boundary-bare-m.go | 2 +- ...-gen-boundary-reacquire-new-proc-bare-m.go | 2 +- ...al-proc-gen-boundary-reacquire-new-proc.go | 2 +- .../go122-syscall-steal-proc-gen-boundary.go | 2 +- ...ll-steal-proc-reacquire-new-proc-bare-m.go | 2 +- ...2-syscall-steal-proc-reacquire-new-proc.go | 2 +- .../go122-syscall-steal-proc-self.go | 2 +- .../go122-syscall-steal-proc-simple-bare-m.go | 2 +- .../go122-syscall-steal-proc-simple.go | 2 +- ...2-syscall-steal-proc-sitting-in-syscall.go | 2 +- .../go122-task-across-generations.go | 2 +- .../tests/go122-fail-first-gen-first.test | 9 ++ trace/value.go | 2 +- 53 files changed, 612 insertions(+), 85 deletions(-) create mode 100644 trace/cmd/gotraceeventstats/main.go create mode 100644 trace/parser.go create mode 100644 trace/testdata/generators/go122-fail-first-gen-first.go create mode 100644 trace/testdata/tests/go122-fail-first-gen-first.test diff --git a/trace/base.go b/trace/base.go index fb874dbeb..d3d5db49d 100644 --- a/trace/base.go +++ b/trace/base.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 @@ -65,6 +65,10 @@ type evTable struct { extraStrings []string extraStringIDs map[string]extraStringID nextExtra extraStringID + + // expData contains extra unparsed data that is accessible + // only to ExperimentEvent via an EventExperimental event. + expData map[event.Experiment]*ExperimentalData } // addExtraString adds an extra string to the evTable and returns diff --git a/trace/batch.go b/trace/batch.go index 0bde22d2e..4d6c530f2 100644 --- a/trace/batch.go +++ b/trace/batch.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 @@ -27,22 +27,23 @@ type batch struct { m ThreadID time timestamp data []byte + exp event.Experiment } func (b *batch) isStringsBatch() bool { - return len(b.data) > 0 && event.Type(b.data[0]) == go122.EvStrings + return b.exp == event.NoExperiment && len(b.data) > 0 && event.Type(b.data[0]) == go122.EvStrings } func (b *batch) isStacksBatch() bool { - return len(b.data) > 0 && event.Type(b.data[0]) == go122.EvStacks + return b.exp == event.NoExperiment && len(b.data) > 0 && event.Type(b.data[0]) == go122.EvStacks } func (b *batch) isCPUSamplesBatch() bool { - return len(b.data) > 0 && event.Type(b.data[0]) == go122.EvCPUSamples + return b.exp == event.NoExperiment && len(b.data) > 0 && event.Type(b.data[0]) == go122.EvCPUSamples } func (b *batch) isFreqBatch() bool { - return len(b.data) > 0 && event.Type(b.data[0]) == go122.EvFrequency + return b.exp == event.NoExperiment && len(b.data) > 0 && event.Type(b.data[0]) == go122.EvFrequency } // readBatch reads the next full batch from r. @@ -55,8 +56,18 @@ func readBatch(r interface { if err != nil { return batch{}, 0, err } - if typ := event.Type(b); typ != go122.EvEventBatch { - return batch{}, 0, fmt.Errorf("expected batch event (%s), got %s", go122.EventString(go122.EvEventBatch), go122.EventString(typ)) + if typ := event.Type(b); typ != go122.EvEventBatch && typ != go122.EvExperimentalBatch { + return batch{}, 0, fmt.Errorf("expected batch event, got %s", go122.EventString(typ)) + } + + // Read the experiment of we have one. + exp := event.NoExperiment + if event.Type(b) == go122.EvExperimentalBatch { + e, err := r.ReadByte() + if err != nil { + return batch{}, 0, err + } + exp = event.Experiment(e) } // Read the batch header: gen (generation), thread (M) ID, base timestamp @@ -99,5 +110,6 @@ func readBatch(r interface { m: ThreadID(m), time: timestamp(ts), data: data.Bytes(), + exp: exp, }, gen, nil } diff --git a/trace/batchcursor.go b/trace/batchcursor.go index 958246896..c3b0f518f 100644 --- a/trace/batchcursor.go +++ b/trace/batchcursor.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/batchcursor_test.go b/trace/batchcursor_test.go index b13dbc154..542b32e8b 100644 --- a/trace/batchcursor_test.go +++ b/trace/batchcursor_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/cmd/gotraceeventstats/main.go b/trace/cmd/gotraceeventstats/main.go new file mode 100644 index 000000000..e89f4767c --- /dev/null +++ b/trace/cmd/gotraceeventstats/main.go @@ -0,0 +1,140 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. + +//go:build go1.21 + +package main + +import ( + "cmp" + "encoding/binary" + "flag" + "fmt" + "io" + "log" + "os" + "slices" + "text/tabwriter" + + "golang.org/x/exp/trace/internal/event" + "golang.org/x/exp/trace/internal/raw" +) + +func init() { + flag.Usage = func() { + fmt.Fprintf(flag.CommandLine.Output(), "Usage: %s [mode]\n", os.Args[0]) + fmt.Fprintf(flag.CommandLine.Output(), "\n") + fmt.Fprintf(flag.CommandLine.Output(), "Accepts a trace at stdin.\n") + fmt.Fprintf(flag.CommandLine.Output(), "\n") + fmt.Fprintf(flag.CommandLine.Output(), "Supported modes:") + fmt.Fprintf(flag.CommandLine.Output(), "\n") + fmt.Fprintf(flag.CommandLine.Output(), "* size - dumps size stats\n") + fmt.Fprintf(flag.CommandLine.Output(), "\n") + flag.PrintDefaults() + } + log.SetFlags(0) +} + +func main() { + log.SetPrefix("") + flag.Parse() + + if flag.NArg() != 1 { + log.Print("missing mode argument") + flag.Usage() + os.Exit(1) + } + var err error + switch mode := flag.Arg(0); mode { + case "size": + err = printSizeStats(os.Stdin) + default: + log.Printf("unknown mode %q", mode) + flag.Usage() + os.Exit(1) + } + if err != nil { + log.Fatalf("error: %v", err) + os.Exit(1) + } +} + +func printSizeStats(r io.Reader) error { + cr := countingReader{Reader: r} + tr, err := raw.NewReader(&cr) + if err != nil { + return err + } + type eventStats struct { + typ event.Type + count int + bytes int + } + var stats [256]eventStats + for i := range stats { + stats[i].typ = event.Type(i) + } + eventsRead := 0 + for { + e, err := tr.ReadEvent() + if err == io.EOF { + break + } + if err != nil { + return err + } + s := &stats[e.Ev] + s.count++ + s.bytes += encodedSize(&e) + eventsRead++ + } + slices.SortFunc(stats[:], func(a, b eventStats) int { + return cmp.Compare(b.bytes, a.bytes) + }) + specs := tr.Version().Specs() + w := tabwriter.NewWriter(os.Stdout, 3, 8, 2, ' ', 0) + fmt.Fprintf(w, "Event\tBytes\t%%\tCount\t%%\n") + fmt.Fprintf(w, "-\t-\t-\t-\t-\n") + for i := range stats { + stat := &stats[i] + name := "" + if int(stat.typ) >= len(specs) { + name = fmt.Sprintf("", stat.typ) + } else { + name = specs[stat.typ].Name + } + bytesPct := float64(stat.bytes) / float64(cr.bytesRead) * 100 + countPct := float64(stat.count) / float64(eventsRead) * 100 + fmt.Fprintf(w, "%s\t%d\t%.2f%%\t%d\t%.2f%%\n", name, stat.bytes, bytesPct, stat.count, countPct) + } + w.Flush() + return nil +} + +func encodedSize(e *raw.Event) int { + size := 1 + var buf [binary.MaxVarintLen64]byte + for _, arg := range e.Args { + size += binary.PutUvarint(buf[:], arg) + } + spec := e.Version.Specs()[e.Ev] + if spec.HasData { + size += binary.PutUvarint(buf[:], uint64(len(e.Data))) + size += len(e.Data) + } + return size +} + +type countingReader struct { + io.Reader + bytesRead int +} + +func (r *countingReader) Read(b []byte) (int, error) { + n, err := r.Reader.Read(b) + r.bytesRead += n + return n, err +} diff --git a/trace/cmd/gotraceraw/main.go b/trace/cmd/gotraceraw/main.go index c5441410c..71e8e5bff 100644 --- a/trace/cmd/gotraceraw/main.go +++ b/trace/cmd/gotraceraw/main.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/cmd/gotracevalidate/main.go b/trace/cmd/gotracevalidate/main.go index cb7166caa..41d2ffeef 100644 --- a/trace/cmd/gotracevalidate/main.go +++ b/trace/cmd/gotracevalidate/main.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/event.go b/trace/event.go index 2a76eb892..6fb6f608b 100644 --- a/trace/event.go +++ b/trace/event.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 @@ -80,8 +80,13 @@ const ( // EventLog represents a runtime/trace.Log call. EventLog - // Transitions in state for some resource. + // EventStateTransition represents a state change for some resource. EventStateTransition + + // EventExperimental is an experimental event that is unvalidated and exposed in a raw form. + // Users are expected to understand the format and perform their own validation. These events + // may always be safely ignored. + EventExperimental ) // String returns a string form of the EventKind. @@ -107,6 +112,7 @@ var eventKindStrings = [...]string{ EventRegionEnd: "RegionEnd", EventLog: "Log", EventStateTransition: "StateTransition", + EventExperimental: "Experimental", } const maxTime = Time(math.MaxInt64) @@ -304,6 +310,42 @@ type StackFrame struct { Line uint64 } +// ExperimentalEvent presents a raw view of an experimental event's arguments and thier names. +type ExperimentalEvent struct { + // Name is the name of the event. + Name string + + // ArgNames is the names of the event's arguments in order. + // This may refer to a globally shared slice. Copy before mutating. + ArgNames []string + + // Args contains the event's arguments. + Args []uint64 + + // Data is additional unparsed data that is associated with the experimental event. + // Data is likely to be shared across many ExperimentalEvents, so callers that parse + // Data are encouraged to cache the parse result and look it up by the value of Data. + Data *ExperimentalData +} + +// ExperimentalData represents some raw and unparsed sidecar data present in the trace that is +// associated with certain kinds of experimental events. For example, this data may contain +// tables needed to interpret ExperimentalEvent arguments, or the ExperimentEvent could just be +// a placeholder for a differently encoded event that's actually present in the experimental data. +type ExperimentalData struct { + // Batches contain the actual experimental data, along with metadata about each batch. + Batches []ExperimentalBatch +} + +// ExperimentalBatch represents a packet of unparsed data along with metadata about that packet. +type ExperimentalBatch struct { + // Thread is the ID of the thread that produced a packet of data. + Thread ThreadID + + // Data is a packet of unparsed data all produced by one thread. + Data []byte +} + // Event represents a single event in the trace. type Event struct { table *evTable @@ -617,6 +659,23 @@ func (e Event) StateTransition() StateTransition { return s } +// Experimental returns a view of the raw event for an experimental event. +// +// Panics if Kind != EventExperimental. +func (e Event) Experimental() ExperimentalEvent { + if e.Kind() != EventExperimental { + panic("Experimental called on non-Experimental event") + } + spec := go122.Specs()[e.base.typ] + argNames := spec.Args[1:] + return ExperimentalEvent{ + Name: spec.Name, + ArgNames: argNames, // Skip timestamp; already handled. + Args: e.base.args[1 : 1+len(argNames)], + Data: e.table.expData[spec.Experiment], + } +} + const evSync = ^event.Type(0) var go122Type2Kind = [...]EventKind{ @@ -661,6 +720,15 @@ var go122Type2Kind = [...]EventKind{ go122.EvGoSwitchDestroy: EventStateTransition, go122.EvGoCreateBlocked: EventStateTransition, go122.EvGoStatusStack: EventStateTransition, + go122.EvSpan: EventExperimental, + go122.EvSpanAlloc: EventExperimental, + go122.EvSpanFree: EventExperimental, + go122.EvHeapObject: EventExperimental, + go122.EvHeapObjectAlloc: EventExperimental, + go122.EvHeapObjectFree: EventExperimental, + go122.EvGoroutineStack: EventExperimental, + go122.EvGoroutineStackAlloc: EventExperimental, + go122.EvGoroutineStackFree: EventExperimental, evSync: EventSync, } @@ -737,6 +805,9 @@ func (e Event) String() string { return true }) } + case EventExperimental: + r := e.Experimental() + fmt.Fprintf(&sb, " Name=%s ArgNames=%v Args=%v", r.Name, r.ArgNames, r.Args) } if stk := e.Stack(); stk != NoStack { fmt.Fprintln(&sb) diff --git a/trace/event_test.go b/trace/event_test.go index 453c485b7..7906b2d5d 100644 --- a/trace/event_test.go +++ b/trace/event_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/generation.go b/trace/generation.go index 4ff535a35..6b8c8b15b 100644 --- a/trace/generation.go +++ b/trace/generation.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 @@ -45,6 +45,9 @@ type spilledBatch struct { // out of r. spill is the first batch of the new generation (already buffered and // parsed from reading the last generation). Returns the generation and the first // batch read of the next generation, if any. +// +// If gen is non-nil, it is valid and must be processed before handling the returned +// error. func readGeneration(r *bufio.Reader, spill *spilledBatch) (*generation, *spilledBatch, error) { g := &generation{ evTable: &evTable{ @@ -62,12 +65,20 @@ func readGeneration(r *bufio.Reader, spill *spilledBatch) (*generation, *spilled } // Read batches one at a time until we either hit EOF or // the next generation. + var spillErr error for { b, gen, err := readBatch(r) if err == io.EOF { break } if err != nil { + if g.gen != 0 { + // This is an error reading the first batch of the next generation. + // This is fine. Let's forge ahead assuming that what we've got so + // far is fine. + spillErr = err + break + } return nil, nil, err } if gen == 0 { @@ -125,7 +136,7 @@ func readGeneration(r *bufio.Reader, spill *spilledBatch) (*generation, *spilled slices.SortFunc(g.cpuSamples, func(a, b cpuSample) int { return cmp.Compare(a.time, b.time) }) - return g, spill, nil + return g, spill, spillErr } // processBatch adds the batch to the generation. @@ -154,6 +165,10 @@ func processBatch(g *generation, b batch) error { return fmt.Errorf("found multiple frequency events") } g.freq = freq + case b.exp != event.NoExperiment: + if err := addExperimentalData(g.expData, b); err != nil { + return err + } default: g.batches[b.m] = append(g.batches[b.m], b) } @@ -416,3 +431,20 @@ func parseFreq(b batch) (frequency, error) { // Convert to nanoseconds per timestamp unit. return frequency(1.0 / (float64(f) / 1e9)), nil } + +// addExperimentalData takes an experimental batch and adds it to the ExperimentalData +// for the experiment its a part of. +func addExperimentalData(expData map[event.Experiment]*ExperimentalData, b batch) error { + if b.exp == event.NoExperiment { + return fmt.Errorf("internal error: addExperimentalData called on non-experimental batch") + } + ed, ok := expData[b.exp] + if !ok { + ed = new(ExperimentalData) + } + ed.Batches = append(ed.Batches, ExperimentalBatch{ + Thread: b.m, + Data: b.data, + }) + return nil +} diff --git a/trace/internal/event/event.go b/trace/internal/event/event.go index 4b5da1fdf..cfabfa6cb 100644 --- a/trace/internal/event/event.go +++ b/trace/internal/event/event.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 @@ -32,6 +32,15 @@ type Spec struct { // in the ArgTypes variable. Args []string + // StringIDs indicates which of the arguments are string IDs. + StringIDs []int + + // StackIDs indicates which of the arguments are stack IDs. + // + // The list is not sorted. The first index always refers to + // the main stack for the current execution context of the event. + StackIDs []int + // StartEv indicates the event type of the corresponding "start" // event, if this event is an "end," for a pair of events that // represent a time range. @@ -48,16 +57,9 @@ type Spec struct { // HasData is true if the event has trailer consisting of a // varint length followed by unencoded bytes of some data. - HasData bool - - // StringIDs indicates which of the arguments are string IDs. - StringIDs []int - - // StackIDs indicates which of the arguments are stack IDs. // - // The list is not sorted. The first index always refers to - // the main stack for the current execution context of the event. - StackIDs []int + // An event may not be both a timed event and have data. + HasData bool // IsStack indicates that the event represents a complete // stack trace. Specifically, it means that after the arguments @@ -65,6 +67,11 @@ type Spec struct { // group of 4 represents the PC, file ID, func ID, and line number // in that order. IsStack bool + + // Experiment indicates the ID of an experiment this event is associated + // with. If Experiment is not NoExperiment, then the event is experimental + // and will be exposed as an EventExperiment. + Experiment Experiment } // ArgTypes is a list of valid argument types for use in Args. @@ -91,3 +98,9 @@ func Names(specs []Spec) map[string]Type { } return nameToType } + +// Experiment is an experiment ID that events may be associated with. +type Experiment uint + +// NoExperiment is the reserved ID 0 indicating no experiment. +const NoExperiment Experiment = 0 diff --git a/trace/internal/event/go122/event.go b/trace/internal/event/go122/event.go index 3220771fc..5a8761fcb 100644 --- a/trace/internal/event/go122/event.go +++ b/trace/internal/event/go122/event.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 @@ -77,8 +77,39 @@ const ( EvGoSwitchDestroy // goroutine switch and destroy [timestamp, goroutine ID, goroutine seq] EvGoCreateBlocked // goroutine creation (starts blocked) [timestamp, new goroutine ID, new stack ID, stack ID] - // GoStatus with stack. + // GoStatus with stack. Added in Go 1.23. EvGoStatusStack // goroutine status at the start of a generation, with a stack [timestamp, goroutine ID, M ID, status, stack ID] + + // Batch event for an experimental batch with a custom format. Added in Go 1.23. + EvExperimentalBatch // start of extra data [experiment ID, generation, M ID, timestamp, batch length, batch data...] +) + +// Experiments. +const ( + // AllocFree is the alloc-free events experiment. + AllocFree event.Experiment = 1 + iota +) + +// Experimental events. +const ( + _ event.Type = 127 + iota + + // Experimental events for AllocFree. + + // Experimental heap span events. Added in Go 1.23. + EvSpan // heap span exists [timestamp, id, npages, type/class] + EvSpanAlloc // heap span alloc [timestamp, id, npages, type/class] + EvSpanFree // heap span free [timestamp, id] + + // Experimental heap object events. Added in Go 1.23. + EvHeapObject // heap object exists [timestamp, id, type] + EvHeapObjectAlloc // heap object alloc [timestamp, id, type] + EvHeapObjectFree // heap object free [timestamp, id] + + // Experimental goroutine stack events. Added in Go 1.23. + EvGoroutineStack // stack exists [timestamp, id, order] + EvGoroutineStackAlloc // stack alloc [timestamp, id, order] + EvGoroutineStackFree // stack free [timestamp, id] ) // EventString returns the name of a Go 1.22 event. @@ -129,6 +160,11 @@ var specs = [...]event.Spec{ Name: "Frequency", Args: []string{"freq"}, }, + EvExperimentalBatch: { + Name: "ExperimentalBatch", + Args: []string{"exp", "gen", "m", "time"}, + HasData: true, // Easier to represent for raw readers. + }, // "Timed" Events. EvProcsChange: { @@ -366,6 +402,63 @@ var specs = [...]event.Spec{ IsTimedEvent: true, StackIDs: []int{4}, }, + + // Experimental events. + + EvSpan: { + Name: "Span", + Args: []string{"dt", "id", "npages_value", "kindclass"}, + IsTimedEvent: true, + Experiment: AllocFree, + }, + EvSpanAlloc: { + Name: "SpanAlloc", + Args: []string{"dt", "id", "npages_value", "kindclass"}, + IsTimedEvent: true, + Experiment: AllocFree, + }, + EvSpanFree: { + Name: "SpanFree", + Args: []string{"dt", "id"}, + IsTimedEvent: true, + Experiment: AllocFree, + }, + EvHeapObject: { + Name: "HeapObject", + Args: []string{"dt", "id", "type"}, + IsTimedEvent: true, + Experiment: AllocFree, + }, + EvHeapObjectAlloc: { + Name: "HeapObjectAlloc", + Args: []string{"dt", "id", "type"}, + IsTimedEvent: true, + Experiment: AllocFree, + }, + EvHeapObjectFree: { + Name: "HeapObjectFree", + Args: []string{"dt", "id"}, + IsTimedEvent: true, + Experiment: AllocFree, + }, + EvGoroutineStack: { + Name: "GoroutineStack", + Args: []string{"dt", "id", "order"}, + IsTimedEvent: true, + Experiment: AllocFree, + }, + EvGoroutineStackAlloc: { + Name: "GoroutineStackAlloc", + Args: []string{"dt", "id", "order"}, + IsTimedEvent: true, + Experiment: AllocFree, + }, + EvGoroutineStackFree: { + Name: "GoroutineStackFree", + Args: []string{"dt", "id"}, + IsTimedEvent: true, + Experiment: AllocFree, + }, } type GoStatus uint8 diff --git a/trace/internal/event/requirements.go b/trace/internal/event/requirements.go index 4f41171c8..3482d4e5a 100644 --- a/trace/internal/event/requirements.go +++ b/trace/internal/event/requirements.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/internal/oldtrace/order.go b/trace/internal/oldtrace/order.go index 78f081808..d2945461a 100644 --- a/trace/internal/oldtrace/order.go +++ b/trace/internal/oldtrace/order.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 @@ -130,20 +130,6 @@ func (l *orderEventList) Less(i, j int) bool { return (*l)[i].ev.Ts < (*l)[j].ev.Ts } -type eventList []Event - -func (l *eventList) Len() int { - return len(*l) -} - -func (l *eventList) Less(i, j int) bool { - return (*l)[i].Ts < (*l)[j].Ts -} - -func (l *eventList) Swap(i, j int) { - (*l)[i], (*l)[j] = (*l)[j], (*l)[i] -} - func (h *orderEventList) Push(x orderEvent) { *h = append(*h, x) heapUp(h, len(*h)-1) diff --git a/trace/internal/oldtrace/parser.go b/trace/internal/oldtrace/parser.go index 8ab3773dd..4e673bd48 100644 --- a/trace/internal/oldtrace/parser.go +++ b/trace/internal/oldtrace/parser.go @@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 // Package oldtrace implements a parser for Go execution traces from versions // 1.11–1.21. // -// The package started as a copy of Go 1.19's internal/trace, but has been +// The package started as a copy of Go 1.19's golang.org/x/exp/trace, but has been // optimized to be faster while using less memory and fewer allocations. It has // been further modified for the specific purpose of converting traces to the // new 1.22+ format. @@ -17,6 +17,7 @@ package oldtrace import ( "bytes" + "cmp" "encoding/binary" "errors" "fmt" @@ -24,6 +25,7 @@ import ( "golang.org/x/exp/trace/internal/version" "io" "math" + "slices" "sort" ) @@ -372,7 +374,9 @@ func (p *parser) parseEventBatches() (Events, error) { // with original timestamps corresponding to when ReadTrace pulled the data // off of the profBuf queue. Re-sort them by the timestamp we captured // inside the signal handler. - sort.Sort((*eventList)(&p.cpuSamples)) + slices.SortFunc(p.cpuSamples, func(a, b Event) int { + return cmp.Compare(a.Ts, b.Ts) + }) allProcs := make([]proc, 0, len(p.batchOffsets)) for pid := range p.batchOffsets { diff --git a/trace/internal/raw/doc.go b/trace/internal/raw/doc.go index 149c60664..a2586b317 100644 --- a/trace/internal/raw/doc.go +++ b/trace/internal/raw/doc.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/internal/raw/event.go b/trace/internal/raw/event.go index b7db0170d..8b77faa2e 100644 --- a/trace/internal/raw/event.go +++ b/trace/internal/raw/event.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/internal/raw/reader.go b/trace/internal/raw/reader.go index bf3ef1833..235fc111f 100644 --- a/trace/internal/raw/reader.go +++ b/trace/internal/raw/reader.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/internal/raw/textreader.go b/trace/internal/raw/textreader.go index 05de34c1d..a544449cc 100644 --- a/trace/internal/raw/textreader.go +++ b/trace/internal/raw/textreader.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/internal/raw/textwriter.go b/trace/internal/raw/textwriter.go index 8eaf35986..c0f35b5b2 100644 --- a/trace/internal/raw/textwriter.go +++ b/trace/internal/raw/textwriter.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/internal/raw/writer.go b/trace/internal/raw/writer.go index f82b55987..2384da8d1 100644 --- a/trace/internal/raw/writer.go +++ b/trace/internal/raw/writer.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/internal/testgen/go122/trace.go b/trace/internal/testgen/go122/trace.go index d371e0c80..511414a58 100644 --- a/trace/internal/testgen/go122/trace.go +++ b/trace/internal/testgen/go122/trace.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/internal/testtrace/expectation.go b/trace/internal/testtrace/expectation.go index 8caaeb952..e8084e578 100644 --- a/trace/internal/testtrace/expectation.go +++ b/trace/internal/testtrace/expectation.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/internal/testtrace/format.go b/trace/internal/testtrace/format.go index d7f61a1c3..474a4e7fc 100644 --- a/trace/internal/testtrace/format.go +++ b/trace/internal/testtrace/format.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/internal/testtrace/validation.go b/trace/internal/testtrace/validation.go index ddbf0b6e3..717cc2258 100644 --- a/trace/internal/testtrace/validation.go +++ b/trace/internal/testtrace/validation.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/internal/version/version.go b/trace/internal/version/version.go index 1dc0dcda1..c5e638acb 100644 --- a/trace/internal/version/version.go +++ b/trace/internal/version/version.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/oldtrace.go b/trace/oldtrace.go index a0517924b..4777a686f 100644 --- a/trace/oldtrace.go +++ b/trace/oldtrace.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/order.go b/trace/order.go index fec408793..91c7e25df 100644 --- a/trace/order.go +++ b/trace/order.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 @@ -147,6 +147,23 @@ var orderingDispatch = [256]orderingHandleFunc{ // GoStatus event with a stack. Added in Go 1.23. go122.EvGoStatusStack: (*ordering).advanceGoStatus, + + // Experimental events. + + // Experimental heap span events. Added in Go 1.23. + go122.EvSpan: (*ordering).advanceAllocFree, + go122.EvSpanAlloc: (*ordering).advanceAllocFree, + go122.EvSpanFree: (*ordering).advanceAllocFree, + + // Experimental heap object events. Added in Go 1.23. + go122.EvHeapObject: (*ordering).advanceAllocFree, + go122.EvHeapObjectAlloc: (*ordering).advanceAllocFree, + go122.EvHeapObjectFree: (*ordering).advanceAllocFree, + + // Experimental goroutine stack events. Added in Go 1.23. + go122.EvGoroutineStack: (*ordering).advanceAllocFree, + go122.EvGoroutineStackAlloc: (*ordering).advanceAllocFree, + go122.EvGoroutineStackFree: (*ordering).advanceAllocFree, } func (o *ordering) advanceProcStatus(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) { @@ -1062,6 +1079,15 @@ func (o *ordering) advanceGoRangeEnd(ev *baseEvent, evt *evTable, m ThreadID, ge return curCtx, true, nil } +func (o *ordering) advanceAllocFree(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) { + // Handle simple instantaneous events that may or may not have a P. + if err := validateCtx(curCtx, event.SchedReqs{Thread: event.MustHave, Proc: event.MayHave, Goroutine: event.MayHave}); err != nil { + return curCtx, false, err + } + o.queue.push(Event{table: evt, ctx: curCtx, base: *ev}) + return curCtx, true, nil +} + // Next returns the next event in the ordering. func (o *ordering) Next() (Event, bool) { return o.queue.pop() @@ -1240,7 +1266,7 @@ func (s *rangeState) hasRange(typ rangeType) bool { return false } -// endRange ends a special range in time on the goroutine. +// endsRange ends a special range in time on the goroutine. // // This must line up with the start event type of the range the goroutine is currently in. func (s *rangeState) endRange(typ event.Type) (stringID, error) { diff --git a/trace/order_test.go b/trace/order_test.go index ee9e3c6df..5c0d94a31 100644 --- a/trace/order_test.go +++ b/trace/order_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/parser.go b/trace/parser.go new file mode 100644 index 000000000..b3bdd139e --- /dev/null +++ b/trace/parser.go @@ -0,0 +1,83 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. + +//go:build go1.21 + +package trace + +// Frame is a frame in stack traces. +type Frame struct { + PC uint64 + Fn string + File string + Line int +} + +const ( + // Special P identifiers: + FakeP = 1000000 + iota + TimerP // depicts timer unblocks + NetpollP // depicts network unblocks + SyscallP // depicts returns from syscalls + GCP // depicts GC state + ProfileP // depicts recording of CPU profile samples +) + +// Event types in the trace. +// Verbatim copy from src/runtime/trace.go with the "trace" prefix removed. +const ( + EvNone = 0 // unused + EvBatch = 1 // start of per-P batch of events [pid, timestamp] + EvFrequency = 2 // contains tracer timer frequency [frequency (ticks per second)] + EvStack = 3 // stack [stack id, number of PCs, array of {PC, func string ID, file string ID, line}] + EvGomaxprocs = 4 // current value of GOMAXPROCS [timestamp, GOMAXPROCS, stack id] + EvProcStart = 5 // start of P [timestamp, thread id] + EvProcStop = 6 // stop of P [timestamp] + EvGCStart = 7 // GC start [timestamp, seq, stack id] + EvGCDone = 8 // GC done [timestamp] + EvSTWStart = 9 // GC mark termination start [timestamp, kind] + EvSTWDone = 10 // GC mark termination done [timestamp] + EvGCSweepStart = 11 // GC sweep start [timestamp, stack id] + EvGCSweepDone = 12 // GC sweep done [timestamp, swept, reclaimed] + EvGoCreate = 13 // goroutine creation [timestamp, new goroutine id, new stack id, stack id] + EvGoStart = 14 // goroutine starts running [timestamp, goroutine id, seq] + EvGoEnd = 15 // goroutine ends [timestamp] + EvGoStop = 16 // goroutine stops (like in select{}) [timestamp, stack] + EvGoSched = 17 // goroutine calls Gosched [timestamp, stack] + EvGoPreempt = 18 // goroutine is preempted [timestamp, stack] + EvGoSleep = 19 // goroutine calls Sleep [timestamp, stack] + EvGoBlock = 20 // goroutine blocks [timestamp, stack] + EvGoUnblock = 21 // goroutine is unblocked [timestamp, goroutine id, seq, stack] + EvGoBlockSend = 22 // goroutine blocks on chan send [timestamp, stack] + EvGoBlockRecv = 23 // goroutine blocks on chan recv [timestamp, stack] + EvGoBlockSelect = 24 // goroutine blocks on select [timestamp, stack] + EvGoBlockSync = 25 // goroutine blocks on Mutex/RWMutex [timestamp, stack] + EvGoBlockCond = 26 // goroutine blocks on Cond [timestamp, stack] + EvGoBlockNet = 27 // goroutine blocks on network [timestamp, stack] + EvGoSysCall = 28 // syscall enter [timestamp, stack] + EvGoSysExit = 29 // syscall exit [timestamp, goroutine id, seq, real timestamp] + EvGoSysBlock = 30 // syscall blocks [timestamp] + EvGoWaiting = 31 // denotes that goroutine is blocked when tracing starts [timestamp, goroutine id] + EvGoInSyscall = 32 // denotes that goroutine is in syscall when tracing starts [timestamp, goroutine id] + EvHeapAlloc = 33 // gcController.heapLive change [timestamp, heap live bytes] + EvHeapGoal = 34 // gcController.heapGoal change [timestamp, heap goal bytes] + EvTimerGoroutine = 35 // denotes timer goroutine [timer goroutine id] + EvFutileWakeup = 36 // denotes that the previous wakeup of this goroutine was futile [timestamp] + EvString = 37 // string dictionary entry [ID, length, string] + EvGoStartLocal = 38 // goroutine starts running on the same P as the last event [timestamp, goroutine id] + EvGoUnblockLocal = 39 // goroutine is unblocked on the same P as the last event [timestamp, goroutine id, stack] + EvGoSysExitLocal = 40 // syscall exit on the same P as the last event [timestamp, goroutine id, real timestamp] + EvGoStartLabel = 41 // goroutine starts running with label [timestamp, goroutine id, seq, label string id] + EvGoBlockGC = 42 // goroutine blocks on GC assist [timestamp, stack] + EvGCMarkAssistStart = 43 // GC mark assist start [timestamp, stack] + EvGCMarkAssistDone = 44 // GC mark assist done [timestamp] + EvUserTaskCreate = 45 // trace.NewTask [timestamp, internal task id, internal parent id, name string, stack] + EvUserTaskEnd = 46 // end of task [timestamp, internal task id, stack] + EvUserRegion = 47 // trace.WithRegion [timestamp, internal task id, mode(0:start, 1:end), name string, stack] + EvUserLog = 48 // trace.Log [timestamp, internal id, key string id, stack, value string] + EvCPUSample = 49 // CPU profiling sample [timestamp, real timestamp, real P id (-1 when absent), goroutine id, stack] + EvCount = 50 +) diff --git a/trace/reader.go b/trace/reader.go index 315c5b276..eb83539ab 100644 --- a/trace/reader.go +++ b/trace/reader.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 @@ -26,6 +26,7 @@ type Reader struct { lastTs Time gen *generation spill *spilledBatch + spillErr error // error from reading spill frontier []*batchCursor cpuSamples []cpuSample order ordering @@ -122,6 +123,9 @@ func (r *Reader) ReadEvent() (e Event, err error) { r.emittedSync = true return syncEvent(r.gen.evTable, r.lastTs), nil } + if r.spillErr != nil { + return Event{}, r.spillErr + } if r.gen != nil && r.spill == nil { // If we have a generation from the last read, // and there's nothing left in the frontier, and @@ -131,10 +135,12 @@ func (r *Reader) ReadEvent() (e Event, err error) { return Event{}, io.EOF } // Read the next generation. + var err error r.gen, r.spill, err = readGeneration(r.r, r.spill) - if err != nil { + if r.gen == nil { return Event{}, err } + r.spillErr = err // Reset CPU samples cursor. r.cpuSamples = r.gen.cpuSamples diff --git a/trace/reader_test.go b/trace/reader_test.go index 421e0449e..a33e76a5a 100644 --- a/trace/reader_test.go +++ b/trace/reader_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/resources.go b/trace/resources.go index 2b152ebff..f5ebc8ee7 100644 --- a/trace/resources.go +++ b/trace/resources.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/testdata/generate.go b/trace/testdata/generate.go index 81b64d278..722639a6e 100644 --- a/trace/testdata/generate.go +++ b/trace/testdata/generate.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/testdata/generators/go122-confuse-seq-across-generations.go b/trace/testdata/generators/go122-confuse-seq-across-generations.go index 83bb8e651..487fc2d8c 100644 --- a/trace/testdata/generators/go122-confuse-seq-across-generations.go +++ b/trace/testdata/generators/go122-confuse-seq-across-generations.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/testdata/generators/go122-create-syscall-reuse-thread-id.go b/trace/testdata/generators/go122-create-syscall-reuse-thread-id.go index 01bee41a3..fbe710610 100644 --- a/trace/testdata/generators/go122-create-syscall-reuse-thread-id.go +++ b/trace/testdata/generators/go122-create-syscall-reuse-thread-id.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/testdata/generators/go122-create-syscall-with-p.go b/trace/testdata/generators/go122-create-syscall-with-p.go index 4d4d208fe..5af3baeba 100644 --- a/trace/testdata/generators/go122-create-syscall-with-p.go +++ b/trace/testdata/generators/go122-create-syscall-with-p.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/testdata/generators/go122-fail-first-gen-first.go b/trace/testdata/generators/go122-fail-first-gen-first.go new file mode 100644 index 000000000..3c5659681 --- /dev/null +++ b/trace/testdata/generators/go122-fail-first-gen-first.go @@ -0,0 +1,48 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. + +//go:build go1.21 + +// Regression test for #55160. +// +// The issue is that the parser reads ahead to the first batch of the +// next generation to find generation boundaries, but if it finds an +// error, it needs to delay handling that error until later. Previously +// it would handle that error immediately and a totally valid generation +// would be skipped for parsing and rejected because of an error in a +// batch in the following generation. +// +// This test captures this behavior by making both the first generation +// and second generation bad. It requires that the issue in the first +// generation, which is caught when actually ordering events, be reported +// instead of the second one. + +package main + +import ( + "golang.org/x/exp/trace/internal/event/go122" + testgen "golang.org/x/exp/trace/internal/testgen/go122" +) + +func main() { + testgen.Main(gen) +} + +func gen(t *testgen.Trace) { + // A running goroutine emits a task begin. + t.RawEvent(go122.EvEventBatch, nil, 1 /*gen*/, 0 /*thread ID*/, 0 /*timestamp*/, 5 /*batch length*/) + t.RawEvent(go122.EvFrequency, nil, 15625000) + + // A running goroutine emits a task begin. + t.RawEvent(go122.EvEventBatch, nil, 1 /*gen*/, 0 /*thread ID*/, 0 /*timestamp*/, 5 /*batch length*/) + t.RawEvent(go122.EvGoCreate, nil, 0 /*timestamp delta*/, 1 /*go ID*/, 0, 0) + + // Write an invalid batch event for the next generation. + t.RawEvent(go122.EvEventBatch, nil, 2 /*gen*/, 0 /*thread ID*/, 0 /*timestamp*/, 50 /*batch length (invalid)*/) + + // We should fail at the first issue, not the second one. + t.ExpectFailure("expected a proc but didn't have one") +} diff --git a/trace/testdata/generators/go122-go-create-without-running-g.go b/trace/testdata/generators/go122-go-create-without-running-g.go index 10d00207f..8d89f81d0 100644 --- a/trace/testdata/generators/go122-go-create-without-running-g.go +++ b/trace/testdata/generators/go122-go-create-without-running-g.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/testdata/generators/go122-syscall-steal-proc-ambiguous.go b/trace/testdata/generators/go122-syscall-steal-proc-ambiguous.go index 9b98749ba..41978b481 100644 --- a/trace/testdata/generators/go122-syscall-steal-proc-ambiguous.go +++ b/trace/testdata/generators/go122-syscall-steal-proc-ambiguous.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/testdata/generators/go122-syscall-steal-proc-gen-boundary-bare-m.go b/trace/testdata/generators/go122-syscall-steal-proc-gen-boundary-bare-m.go index 1db4cd9d6..1795dd477 100644 --- a/trace/testdata/generators/go122-syscall-steal-proc-gen-boundary-bare-m.go +++ b/trace/testdata/generators/go122-syscall-steal-proc-gen-boundary-bare-m.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/testdata/generators/go122-syscall-steal-proc-gen-boundary-reacquire-new-proc-bare-m.go b/trace/testdata/generators/go122-syscall-steal-proc-gen-boundary-reacquire-new-proc-bare-m.go index ab0574de0..75bb0332b 100644 --- a/trace/testdata/generators/go122-syscall-steal-proc-gen-boundary-reacquire-new-proc-bare-m.go +++ b/trace/testdata/generators/go122-syscall-steal-proc-gen-boundary-reacquire-new-proc-bare-m.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/testdata/generators/go122-syscall-steal-proc-gen-boundary-reacquire-new-proc.go b/trace/testdata/generators/go122-syscall-steal-proc-gen-boundary-reacquire-new-proc.go index 74c6c8935..9215ee44d 100644 --- a/trace/testdata/generators/go122-syscall-steal-proc-gen-boundary-reacquire-new-proc.go +++ b/trace/testdata/generators/go122-syscall-steal-proc-gen-boundary-reacquire-new-proc.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/testdata/generators/go122-syscall-steal-proc-gen-boundary.go b/trace/testdata/generators/go122-syscall-steal-proc-gen-boundary.go index deb117077..8134ca67f 100644 --- a/trace/testdata/generators/go122-syscall-steal-proc-gen-boundary.go +++ b/trace/testdata/generators/go122-syscall-steal-proc-gen-boundary.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/testdata/generators/go122-syscall-steal-proc-reacquire-new-proc-bare-m.go b/trace/testdata/generators/go122-syscall-steal-proc-reacquire-new-proc-bare-m.go index 43b676752..1b2e25d4c 100644 --- a/trace/testdata/generators/go122-syscall-steal-proc-reacquire-new-proc-bare-m.go +++ b/trace/testdata/generators/go122-syscall-steal-proc-reacquire-new-proc-bare-m.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/testdata/generators/go122-syscall-steal-proc-reacquire-new-proc.go b/trace/testdata/generators/go122-syscall-steal-proc-reacquire-new-proc.go index 187829eb3..1ee3c6627 100644 --- a/trace/testdata/generators/go122-syscall-steal-proc-reacquire-new-proc.go +++ b/trace/testdata/generators/go122-syscall-steal-proc-reacquire-new-proc.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/testdata/generators/go122-syscall-steal-proc-self.go b/trace/testdata/generators/go122-syscall-steal-proc-self.go index 5abbcdeed..bae0929c8 100644 --- a/trace/testdata/generators/go122-syscall-steal-proc-self.go +++ b/trace/testdata/generators/go122-syscall-steal-proc-self.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/testdata/generators/go122-syscall-steal-proc-simple-bare-m.go b/trace/testdata/generators/go122-syscall-steal-proc-simple-bare-m.go index 8e4a00b5e..847c961ec 100644 --- a/trace/testdata/generators/go122-syscall-steal-proc-simple-bare-m.go +++ b/trace/testdata/generators/go122-syscall-steal-proc-simple-bare-m.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/testdata/generators/go122-syscall-steal-proc-simple.go b/trace/testdata/generators/go122-syscall-steal-proc-simple.go index e2f7a6883..78f936f85 100644 --- a/trace/testdata/generators/go122-syscall-steal-proc-simple.go +++ b/trace/testdata/generators/go122-syscall-steal-proc-simple.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/testdata/generators/go122-syscall-steal-proc-sitting-in-syscall.go b/trace/testdata/generators/go122-syscall-steal-proc-sitting-in-syscall.go index f78120d2d..61dda3884 100644 --- a/trace/testdata/generators/go122-syscall-steal-proc-sitting-in-syscall.go +++ b/trace/testdata/generators/go122-syscall-steal-proc-sitting-in-syscall.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/testdata/generators/go122-task-across-generations.go b/trace/testdata/generators/go122-task-across-generations.go index 1be0161b8..27ce4e40c 100644 --- a/trace/testdata/generators/go122-task-across-generations.go +++ b/trace/testdata/generators/go122-task-across-generations.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21 diff --git a/trace/testdata/tests/go122-fail-first-gen-first.test b/trace/testdata/tests/go122-fail-first-gen-first.test new file mode 100644 index 000000000..cc4240de4 --- /dev/null +++ b/trace/testdata/tests/go122-fail-first-gen-first.test @@ -0,0 +1,9 @@ +-- expect -- +FAILURE "expected a proc but didn't have one" +-- trace -- +Trace Go1.22 +EventBatch gen=1 m=0 time=0 size=5 +Frequency freq=15625000 +EventBatch gen=1 m=0 time=0 size=5 +GoCreate dt=0 new_g=1 new_stack=0 stack=0 +EventBatch gen=2 m=0 time=0 size=50 diff --git a/trace/value.go b/trace/value.go index 629269a06..577105d8e 100644 --- a/trace/value.go +++ b/trace/value.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Code generated by "gen.bash" from internal/trace/v2; DO NOT EDIT. +// Code generated by "gen.bash" from internal/trace; DO NOT EDIT. //go:build go1.21