From 93d18d7e34b8aac3374a4710606eb1702f2d44ff Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 8 Apr 2024 22:35:37 +0000 Subject: [PATCH] trace: regenerate trace from go@5879bf7 [git-generate] cd trace ./gen.bash $HOME/work/go Change-Id: Iaf2c333272830c8ee70faed9107b16671a9c169a Reviewed-on: https://go-review.googlesource.com/c/exp/+/577262 Reviewed-by: Nicolas Hillegeer Auto-Submit: Nicolas Hillegeer LUCI-TryBot-Result: Go LUCI Commit-Queue: Nicolas Hillegeer Auto-Submit: Michael Knyszek --- trace/base.go | 14 ++++-- trace/event.go | 3 +- trace/internal/event/go122/event.go | 9 ++++ trace/oldtrace.go | 69 +++++++++++++++-------------- trace/order.go | 3 ++ trace/reader_test.go | 2 +- 6 files changed, 61 insertions(+), 39 deletions(-) diff --git a/trace/base.go b/trace/base.go index 86585b1bb..fb874dbeb 100644 --- a/trace/base.go +++ b/trace/base.go @@ -22,15 +22,23 @@ import ( ) // maxArgs is the maximum number of arguments for "plain" events, -// i.e. anything that could reasonably be represented as a Base. -const maxArgs = 5 +// i.e. anything that could reasonably be represented as a baseEvent. +// +// TODO(mknyszek): This is only 6 instead of 5 because GoStatusStack +// has 5 arguments and needs to smuggle in a 6th. Figure out a way to +// shrink this in the future. +const maxArgs = 6 + +// timedEventArgs is an array that is able to hold the arguments for any +// timed event. +type timedEventArgs [maxArgs - 1]uint64 // baseEvent is the basic unprocessed event. This serves as a common // fundamental data structure across. type baseEvent struct { typ event.Type time Time - args [maxArgs - 1]uint64 + args timedEventArgs } // extra returns a slice representing extra available space in args diff --git a/trace/event.go b/trace/event.go index 962a63c74..2a76eb892 100644 --- a/trace/event.go +++ b/trace/event.go @@ -608,7 +608,7 @@ func (e Event) StateTransition() StateTransition { case go122.EvGoSyscallEndBlocked: s = goStateTransition(e.ctx.G, GoSyscall, GoRunnable) s.Stack = e.Stack() // This event references the resource the event happened on. - case go122.EvGoStatus: + case go122.EvGoStatus, go122.EvGoStatusStack: // N.B. ordering.advance populates e.base.extra. s = goStateTransition(GoID(e.base.args[0]), GoState(e.base.extra(version.Go122)[0]), go122GoStatus2GoState[e.base.args[2]]) default: @@ -660,6 +660,7 @@ var go122Type2Kind = [...]EventKind{ go122.EvGoSwitch: EventStateTransition, go122.EvGoSwitchDestroy: EventStateTransition, go122.EvGoCreateBlocked: EventStateTransition, + go122.EvGoStatusStack: EventStateTransition, evSync: EventSync, } diff --git a/trace/internal/event/go122/event.go b/trace/internal/event/go122/event.go index 2baf9ceac..3220771fc 100644 --- a/trace/internal/event/go122/event.go +++ b/trace/internal/event/go122/event.go @@ -76,6 +76,9 @@ const ( EvGoSwitch // goroutine switch (coroswitch) [timestamp, goroutine ID, goroutine seq] 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. + EvGoStatusStack // goroutine status at the start of a generation, with a stack [timestamp, goroutine ID, M ID, status, stack ID] ) // EventString returns the name of a Go 1.22 event. @@ -357,6 +360,12 @@ var specs = [...]event.Spec{ IsTimedEvent: true, StackIDs: []int{3, 2}, }, + EvGoStatusStack: { + Name: "GoStatusStack", + Args: []string{"dt", "g", "m", "gstatus", "stack"}, + IsTimedEvent: true, + StackIDs: []int{4}, + }, } type GoStatus uint8 diff --git a/trace/oldtrace.go b/trace/oldtrace.go index c69870990..a0517924b 100644 --- a/trace/oldtrace.go +++ b/trace/oldtrace.go @@ -258,7 +258,8 @@ var errSkip = errors.New("skip event") // returns a descriptive error. func (it *oldTraceConverter) convertEvent(ev *oldtrace.Event) (OUT Event, ERR error) { var mappedType event.Type - mappedArgs := ev.Args + var mappedArgs timedEventArgs + copy(mappedArgs[:], ev.Args[:]) switch ev.Type { case oldtrace.EvGomaxprocs: @@ -282,7 +283,7 @@ func (it *oldTraceConverter) convertEvent(ev *oldtrace.Event) (OUT Event, ERR er base: baseEvent{ typ: go122.EvGoStatus, time: Time(ev.Ts), - args: [4]uint64{uint64(gid), ^uint64(0), uint64(go122.GoRunnable)}, + args: timedEventArgs{uint64(gid), ^uint64(0), uint64(go122.GoRunnable)}, }, }) } @@ -293,20 +294,20 @@ func (it *oldTraceConverter) convertEvent(ev *oldtrace.Event) (OUT Event, ERR er it.procMs[ProcID(ev.P)] = ThreadID(ev.Args[0]) if _, ok := it.seenProcs[ProcID(ev.P)]; ok { mappedType = go122.EvProcStart - mappedArgs = [4]uint64{uint64(ev.P)} + mappedArgs = timedEventArgs{uint64(ev.P)} } else { it.seenProcs[ProcID(ev.P)] = struct{}{} mappedType = go122.EvProcStatus - mappedArgs = [4]uint64{uint64(ev.P), uint64(go122.ProcRunning)} + mappedArgs = timedEventArgs{uint64(ev.P), uint64(go122.ProcRunning)} } case oldtrace.EvProcStop: if _, ok := it.seenProcs[ProcID(ev.P)]; ok { mappedType = go122.EvProcStop - mappedArgs = [4]uint64{uint64(ev.P)} + mappedArgs = timedEventArgs{uint64(ev.P)} } else { it.seenProcs[ProcID(ev.P)] = struct{}{} mappedType = go122.EvProcStatus - mappedArgs = [4]uint64{uint64(ev.P), uint64(go122.ProcIdle)} + mappedArgs = timedEventArgs{uint64(ev.P), uint64(go122.ProcIdle)} } case oldtrace.EvGCStart: mappedType = go122.EvGCBegin @@ -316,10 +317,10 @@ func (it *oldTraceConverter) convertEvent(ev *oldtrace.Event) (OUT Event, ERR er sid := it.builtinToStringID[sSTWUnknown+it.trace.STWReason(ev.Args[0])] it.lastStwReason = sid mappedType = go122.EvSTWBegin - mappedArgs = [4]uint64{uint64(sid)} + mappedArgs = timedEventArgs{uint64(sid)} case oldtrace.EvSTWDone: mappedType = go122.EvSTWEnd - mappedArgs = [4]uint64{it.lastStwReason} + mappedArgs = timedEventArgs{it.lastStwReason} case oldtrace.EvGCSweepStart: mappedType = go122.EvGCSweepBegin case oldtrace.EvGCSweepDone: @@ -333,7 +334,7 @@ func (it *oldTraceConverter) convertEvent(ev *oldtrace.Event) (OUT Event, ERR er case oldtrace.EvGoStart: if it.preInit { mappedType = go122.EvGoStatus - mappedArgs = [4]uint64{ev.Args[0], ^uint64(0), uint64(go122.GoRunning)} + mappedArgs = timedEventArgs{ev.Args[0], ^uint64(0), uint64(go122.GoRunning)} delete(it.createdPreInit, GoID(ev.Args[0])) } else { mappedType = go122.EvGoStart @@ -349,7 +350,7 @@ func (it *oldTraceConverter) convertEvent(ev *oldtrace.Event) (OUT Event, ERR er base: baseEvent{ typ: go122.EvGoLabel, time: Time(ev.Ts), - args: [4]uint64{ev.Args[2]}, + args: timedEventArgs{ev.Args[2]}, }, }} return Event{ @@ -362,49 +363,49 @@ func (it *oldTraceConverter) convertEvent(ev *oldtrace.Event) (OUT Event, ERR er base: baseEvent{ typ: go122.EvGoStart, time: Time(ev.Ts), - args: ev.Args, + args: mappedArgs, }, }, nil case oldtrace.EvGoEnd: mappedType = go122.EvGoDestroy case oldtrace.EvGoStop: mappedType = go122.EvGoBlock - mappedArgs = [4]uint64{uint64(it.builtinToStringID[sForever]), uint64(ev.StkID)} + mappedArgs = timedEventArgs{uint64(it.builtinToStringID[sForever]), uint64(ev.StkID)} case oldtrace.EvGoSched: mappedType = go122.EvGoStop - mappedArgs = [4]uint64{uint64(it.builtinToStringID[sGosched]), uint64(ev.StkID)} + mappedArgs = timedEventArgs{uint64(it.builtinToStringID[sGosched]), uint64(ev.StkID)} case oldtrace.EvGoPreempt: mappedType = go122.EvGoStop - mappedArgs = [4]uint64{uint64(it.builtinToStringID[sPreempted]), uint64(ev.StkID)} + mappedArgs = timedEventArgs{uint64(it.builtinToStringID[sPreempted]), uint64(ev.StkID)} case oldtrace.EvGoSleep: mappedType = go122.EvGoBlock - mappedArgs = [4]uint64{uint64(it.builtinToStringID[sSleep]), uint64(ev.StkID)} + mappedArgs = timedEventArgs{uint64(it.builtinToStringID[sSleep]), uint64(ev.StkID)} case oldtrace.EvGoBlock: mappedType = go122.EvGoBlock - mappedArgs = [4]uint64{uint64(it.builtinToStringID[sEmpty]), uint64(ev.StkID)} + mappedArgs = timedEventArgs{uint64(it.builtinToStringID[sEmpty]), uint64(ev.StkID)} case oldtrace.EvGoUnblock: mappedType = go122.EvGoUnblock case oldtrace.EvGoBlockSend: mappedType = go122.EvGoBlock - mappedArgs = [4]uint64{uint64(it.builtinToStringID[sChanSend]), uint64(ev.StkID)} + mappedArgs = timedEventArgs{uint64(it.builtinToStringID[sChanSend]), uint64(ev.StkID)} case oldtrace.EvGoBlockRecv: mappedType = go122.EvGoBlock - mappedArgs = [4]uint64{uint64(it.builtinToStringID[sChanRecv]), uint64(ev.StkID)} + mappedArgs = timedEventArgs{uint64(it.builtinToStringID[sChanRecv]), uint64(ev.StkID)} case oldtrace.EvGoBlockSelect: mappedType = go122.EvGoBlock - mappedArgs = [4]uint64{uint64(it.builtinToStringID[sSelect]), uint64(ev.StkID)} + mappedArgs = timedEventArgs{uint64(it.builtinToStringID[sSelect]), uint64(ev.StkID)} case oldtrace.EvGoBlockSync: mappedType = go122.EvGoBlock - mappedArgs = [4]uint64{uint64(it.builtinToStringID[sSync]), uint64(ev.StkID)} + mappedArgs = timedEventArgs{uint64(it.builtinToStringID[sSync]), uint64(ev.StkID)} case oldtrace.EvGoBlockCond: mappedType = go122.EvGoBlock - mappedArgs = [4]uint64{uint64(it.builtinToStringID[sSyncCond]), uint64(ev.StkID)} + mappedArgs = timedEventArgs{uint64(it.builtinToStringID[sSyncCond]), uint64(ev.StkID)} case oldtrace.EvGoBlockNet: mappedType = go122.EvGoBlock - mappedArgs = [4]uint64{uint64(it.builtinToStringID[sNetwork]), uint64(ev.StkID)} + mappedArgs = timedEventArgs{uint64(it.builtinToStringID[sNetwork]), uint64(ev.StkID)} case oldtrace.EvGoBlockGC: mappedType = go122.EvGoBlock - mappedArgs = [4]uint64{uint64(it.builtinToStringID[sMarkAssistWait]), uint64(ev.StkID)} + mappedArgs = timedEventArgs{uint64(it.builtinToStringID[sMarkAssistWait]), uint64(ev.StkID)} case oldtrace.EvGoSysCall: // Look for the next event for the same G to determine if the syscall // blocked. @@ -423,7 +424,7 @@ func (it *oldTraceConverter) convertEvent(ev *oldtrace.Event) (OUT Event, ERR er }) if blocked { mappedType = go122.EvGoSyscallBegin - mappedArgs = [4]uint64{1: uint64(ev.StkID)} + mappedArgs = timedEventArgs{1: uint64(ev.StkID)} } else { // Convert the old instantaneous syscall event to a pair of syscall // begin and syscall end and give it the shortest possible duration, @@ -438,7 +439,7 @@ func (it *oldTraceConverter) convertEvent(ev *oldtrace.Event) (OUT Event, ERR er base: baseEvent{ typ: go122.EvGoSyscallBegin, time: Time(ev.Ts), - args: [4]uint64{1: uint64(ev.StkID)}, + args: timedEventArgs{1: uint64(ev.StkID)}, }, } @@ -448,7 +449,7 @@ func (it *oldTraceConverter) convertEvent(ev *oldtrace.Event) (OUT Event, ERR er base: baseEvent{ typ: go122.EvGoSyscallEnd, time: Time(ev.Ts + 1), - args: [4]uint64{}, + args: timedEventArgs{}, }, } @@ -462,14 +463,14 @@ func (it *oldTraceConverter) convertEvent(ev *oldtrace.Event) (OUT Event, ERR er return Event{}, errSkip case oldtrace.EvGoWaiting: mappedType = go122.EvGoStatus - mappedArgs = [4]uint64{ev.Args[0], ^uint64(0), uint64(go122.GoWaiting)} + mappedArgs = timedEventArgs{ev.Args[0], ^uint64(0), uint64(go122.GoWaiting)} delete(it.createdPreInit, GoID(ev.Args[0])) case oldtrace.EvGoInSyscall: mappedType = go122.EvGoStatus // In the new tracer, GoStatus with GoSyscall knows what thread the // syscall is on. In the old tracer, EvGoInSyscall doesn't contain that // information and all we can do here is specify NoThread. - mappedArgs = [4]uint64{ev.Args[0], ^uint64(0), uint64(go122.GoSyscall)} + mappedArgs = timedEventArgs{ev.Args[0], ^uint64(0), uint64(go122.GoSyscall)} delete(it.createdPreInit, GoID(ev.Args[0])) case oldtrace.EvHeapAlloc: mappedType = go122.EvHeapAlloc @@ -485,7 +486,7 @@ func (it *oldTraceConverter) convertEvent(ev *oldtrace.Event) (OUT Event, ERR er if parent == 0 { parent = uint64(NoTask) } - mappedArgs = [4]uint64{ev.Args[0], parent, ev.Args[2], uint64(ev.StkID)} + mappedArgs = timedEventArgs{ev.Args[0], parent, ev.Args[2], uint64(ev.StkID)} name, _ := it.evt.strings.get(stringID(ev.Args[2])) it.tasks[TaskID(ev.Args[0])] = taskState{name: name, parentID: TaskID(ev.Args[1])} case oldtrace.EvUserTaskEnd: @@ -495,14 +496,14 @@ func (it *oldTraceConverter) convertEvent(ev *oldtrace.Event) (OUT Event, ERR er ts, ok := it.tasks[TaskID(ev.Args[0])] if ok { delete(it.tasks, TaskID(ev.Args[0])) - mappedArgs = [4]uint64{ + mappedArgs = timedEventArgs{ ev.Args[0], ev.Args[1], uint64(ts.parentID), uint64(it.evt.addExtraString(ts.name)), } } else { - mappedArgs = [4]uint64{ev.Args[0], ev.Args[1], uint64(NoTask), uint64(it.evt.addExtraString(""))} + mappedArgs = timedEventArgs{ev.Args[0], ev.Args[1], uint64(NoTask), uint64(it.evt.addExtraString(""))} } case oldtrace.EvUserRegion: switch ev.Args[1] { @@ -511,10 +512,10 @@ func (it *oldTraceConverter) convertEvent(ev *oldtrace.Event) (OUT Event, ERR er case 1: // end mappedType = go122.EvUserRegionEnd } - mappedArgs = [4]uint64{ev.Args[0], ev.Args[2], uint64(ev.StkID)} + mappedArgs = timedEventArgs{ev.Args[0], ev.Args[2], uint64(ev.StkID)} case oldtrace.EvUserLog: mappedType = go122.EvUserLog - mappedArgs = [4]uint64{ev.Args[0], ev.Args[1], it.inlineToStringID[ev.Args[3]], uint64(ev.StkID)} + mappedArgs = timedEventArgs{ev.Args[0], ev.Args[1], it.inlineToStringID[ev.Args[3]], uint64(ev.StkID)} case oldtrace.EvCPUSample: mappedType = go122.EvCPUSample // When emitted by the Go 1.22 tracer, CPU samples have 5 arguments: @@ -522,7 +523,7 @@ func (it *oldTraceConverter) convertEvent(ev *oldtrace.Event) (OUT Event, ERR er // they have the arguments stack, M, P, G. // // In Go 1.21, CPU samples did not have Ms. - mappedArgs = [4]uint64{uint64(ev.StkID), ^uint64(0), uint64(ev.P), ev.G} + mappedArgs = timedEventArgs{uint64(ev.StkID), ^uint64(0), uint64(ev.P), ev.G} default: return Event{}, fmt.Errorf("unexpected event type %v", ev.Type) } diff --git a/trace/order.go b/trace/order.go index 089d62388..2e6d96c16 100644 --- a/trace/order.go +++ b/trace/order.go @@ -144,6 +144,9 @@ var orderingDispatch = [256]orderingHandleFunc{ go122.EvGoSwitch: (*ordering).advanceGoSwitch, go122.EvGoSwitchDestroy: (*ordering).advanceGoSwitch, go122.EvGoCreateBlocked: (*ordering).advanceGoCreate, + + // GoStatus event with a stack. Added in Go 1.23. + go122.EvGoStatusStack: (*ordering).advanceGoStatus, } func (o *ordering) advanceProcStatus(ev *baseEvent, evt *evTable, m ThreadID, gen uint64, curCtx schedCtx) (schedCtx, bool, error) { diff --git a/trace/reader_test.go b/trace/reader_test.go index 401441c67..421e0449e 100644 --- a/trace/reader_test.go +++ b/trace/reader_test.go @@ -137,7 +137,7 @@ func dumpTraceToText(t *testing.T, b []byte) string { t.Fatalf("dumping trace: %v", err) } var sb strings.Builder - tw, err := raw.NewTextWriter(&sb, version.Go122) + tw, err := raw.NewTextWriter(&sb, version.Current) if err != nil { t.Fatalf("dumping trace: %v", err) }