Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions internal/tracedb/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,22 @@ select
from goroutines
group by 1
order by running_ns desc, name;

create table gc_ranges (
name text,
scope_kind text,
scope_id bigint,
start_time_ns bigint,
end_time_ns bigint,
duration_ns bigint,
stack_id ubigint,
g bigint,
p bigint
);

create view gc_cycles as
select
row_number() over (order by start_time_ns) as cycle,
start_time_ns, end_time_ns, duration_ns
from gc_ranges
where name = 'GC concurrent mark phase';
76 changes: 76 additions & 0 deletions internal/tracedb/tracedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ func (db *DB) loadTrace(ctx context.Context, r io.Reader) (err error) {

gIdx := map[trace.GoID]*gState{}
pIdx := map[trace.ProcID]*pState{}
rIdx := map[rangeKey]*rangeState{}
for first := true; ; first = false {
var ev trace.Event
if ev, err = tr.ReadEvent(); err == io.EOF {
Expand Down Expand Up @@ -231,6 +232,46 @@ func (db *DB) loadTrace(ctx context.Context, r io.Reader) (err error) {
}
g.time = ev.Time()
}
case trace.EventRangeBegin, trace.EventRangeActive:
r := ev.Range()
key := rangeKey{
name: r.Name,
scopeKind: r.Scope.Kind,
scopeID: scopeIDFromRange(r),
}
rIdx[key] = &rangeState{
start: ev.Time(),
stackID: srcStackID,
g: ev.Goroutine(),
p: ev.Proc(),
}
case trace.EventRangeEnd:
r := ev.Range()
key := rangeKey{
name: r.Name,
scopeKind: r.Scope.Kind,
scopeID: scopeIDFromRange(r),
}
rs, ok := rIdx[key]
if !ok {
break
}
delete(rIdx, key)
dt := uint64(ev.Time() - rs.start)
scopeKind, scopeID := scopeFromRange(r)
if err = l.Append("gc_ranges",
r.Name,
scopeKind,
scopeID,
uint64(rs.start),
uint64(ev.Time()),
dt,
nullableUint64(rs.stackID),
nullableResource(rs.g),
nullableResource(rs.p),
); err != nil {
return
}
}
}
return
Expand Down Expand Up @@ -267,6 +308,41 @@ type pState struct {
time trace.Time
}

type rangeKey struct {
name string
scopeKind trace.ResourceKind
scopeID int64
}

type rangeState struct {
start trace.Time
stackID uint64
g trace.GoID
p trace.ProcID
}

func scopeFromRange(r trace.Range) (kind string, id any) {
switch r.Scope.Kind {
case trace.ResourceGoroutine:
return "goroutine", int64(r.Scope.Goroutine())
case trace.ResourceProc:
return "proc", int64(r.Scope.Proc())
default:
return "none", nil
}
}

func scopeIDFromRange(r trace.Range) int64 {
switch r.Scope.Kind {
case trace.ResourceGoroutine:
return int64(r.Scope.Goroutine())
case trace.ResourceProc:
return int64(r.Scope.Proc())
default:
return 0
}
}

func (db *DB) loader(ctx context.Context) (*loader, error) {
l := &loader{
funcIdx: map[functionKey]*functionRow{},
Expand Down
Loading