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 <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Michael Knyszek <mknyszek@google.com>
This commit is contained in:
Michael Anthony Knyszek 2024-05-24 20:32:24 +00:00 коммит произвёл Gopher Robot
Родитель 4c93da0ed1
Коммит 23cca8864a
53 изменённых файлов: 612 добавлений и 85 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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
}

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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("<unknown (%d)>", 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
}

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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)

Просмотреть файл

@ -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

Просмотреть файл

@ -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
}

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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)

Просмотреть файл

@ -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 {

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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) {

Просмотреть файл

@ -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

83
trace/parser.go Normal file
Просмотреть файл

@ -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
)

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

2
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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

48
trace/testdata/generators/go122-fail-first-gen-first.go поставляемый Normal file
Просмотреть файл

@ -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")
}

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

9
trace/testdata/tests/go122-fail-first-gen-first.test поставляемый Normal file
Просмотреть файл

@ -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

Просмотреть файл

@ -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