main f2d166b

flip_stats.go RawHistoryFolder

1package drm
2
3import "time"
4
5// flipStats are the flip timing counters of one output, reported and
6// reset by the periodic stats entry. They are plain fields owned by the
7// output goroutine. All times are CLOCK_MONOTONIC (kernel flip
8// timestamps and userspace reads), so they tell a late composition from a
9// late read of the event (see accountFlip).
10type flipStats struct {
11	// missedVblanks counts due frame flips whose kernel timestamp is over
12	// 1.5 refresh periods after the previous frame flip (never under VRR,
13	// where the period is not fixed).
14	missedVblanks int
15	// maxInterval is the longest time between two frame flips, of the
16	// frames that were due.
17	maxInterval time.Duration
18	// maxCommitDelay is the longest time a due frame waited between the
19	// moment it was due (wanted, the previous flip landed, or the VRR
20	// flip gap ended) and its commit: late event read, slow composition.
21	maxCommitDelay time.Duration
22	// maxFlipToRead is the longest time between a flip's kernel timestamp
23	// and the output reading its event: the event delivery latency.
24	maxFlipToRead time.Duration
25	// lateFences counts missed vblanks whose fences signalled after the
26	// vblank the frame targeted (never under VRR). Fence times are only
27	// read while flip tracing is on.
28	lateFences int
29	// stateCommits counts state-only commits (cursor, VRR, content type);
30	// stateCarried counts deferred state changes a frame carried instead.
31	// Many state commits while a video plays point at a lost vblank each.
32	stateCommits, stateCarried int
33	// fenceTimeouts counts commits whose CPU fence wait hit its limit
34	// (fencegate.go).
35	fenceTimeouts int
36}
37
38// nominalPeriod is the time between two vblanks at the mode's refresh
39// rate. Under VRR it is the shortest period: the fastest the output
40// flips.
41func (o *Output) nominalPeriod() time.Duration {
42	return time.Duration(int64(time.Second) * 1000 / int64(max(1, o.mode.refreshMilli())))
43}
44
45// refreshPeriod is the time between two vblanks of the current mode (0:
46// not fixed, VRR).
47func (o *Output) refreshPeriod() time.Duration {
48	if o.vrrOn {
49		return 0
50	}
51	return o.nominalPeriod()
52}
53
54// setVRR records the VRR state. The flip interval chain restarts when it
55// changes: the period of the two states differs.
56func (o *Output) setVRR(on bool) {
57	if o.vrrOn != on {
58		o.lastFlipAt = 0
59	}
60	o.vrrOn = on
61}
62
63// accountFlip counts the completion ev of a frame commit made at
64// commitAt for a frame due at wantedAt (0: unknown, the commit time; see
65// pendingFrame.dueAt). All times are CLOCK_MONOTONIC. fenceAt is when the
66// commit's fences signalled (0: none or unknown). It updates lastFlipAt
67// for frame flips and never allocates.
68//
69// An output renders only on change, so a gap after an idle period says
70// nothing about missed vblanks. The interval to the previous flip counts
71// only for a frame that was due: wanted less than one period after the
72// previous flip, so it was meant for the very next vblank, whenever it was
73// committed. A frame that waited for the previous flip's event or for its
74// composition is due as soon as it is wanted. Then:
75//
76//   - a flip over 1.5 periods after the previous one missed a vblank
77//     (never counted under VRR, where the period is not fixed);
78//   - if it missed one and its fences signalled after the vblank it
79//     targeted (the previous flip plus one period), the frame was late: a
80//     late fence. A fence before that vblank is not;
81//   - the commit delay is the time from when the frame was due (wanted,
82//     and not before the previous flip) to its commit. A missed vblank
83//     with a long commit delay and no late fence points at the commit
84//     path: late event read, slow composition on the CPU.
85func (o *Output) accountFlip(ev flipEvent, frame bool, wantedAt, commitAt, fenceAt time.Duration) {
86	if !frame {
87		return
88	}
89	if wantedAt == 0 {
90		wantedAt = commitAt
91	}
92	if prev := o.lastFlipAt; prev != 0 && wantedAt-prev < o.nominalPeriod() {
93		s := &o.flipStats
94		interval := ev.when - prev
95		s.maxInterval = max(s.maxInterval, interval)
96		s.maxCommitDelay = max(s.maxCommitDelay, commitAt-max(wantedAt, prev))
97		if period := o.refreshPeriod(); period != 0 && 2*interval > 3*period {
98			s.missedVblanks++
99			if fenceAt != 0 && fenceAt > prev+period {
100				s.lateFences++
101			}
102		}
103	}
104	o.lastFlipAt = ev.when
105}
106
107// accountRead tracks the delivery latency of the event ev handled at now.
108func (o *Output) accountRead(ev flipEvent, now time.Duration) {
109	o.flipStats.maxFlipToRead = max(o.flipStats.maxFlipToRead, now-ev.when)
110}
111
112// takeFlipStats returns the counters and starts over.
113func (o *Output) takeFlipStats() flipStats {
114	s := o.flipStats
115	o.flipStats = flipStats{}
116	return s
117}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 25

Tags 10

↑↓ moveenter openesc close