v0.1.0 7deb448

benchmark_test.go RawHistoryFolder

1package renderer
2
3import "testing"
4
5func markBenchmarkFrame(f *Frame) {
6	for y := range f.Height {
7		for x := range f.Width {
8			f.Set(x, y, Cell{Rune: rune('A' + (y*f.Width+x)%26), Style: DefaultStyle()})
9		}
10	}
11}
12
13func BenchmarkRendererFullFrameDraw(b *testing.B) {
14	frame := NewFrame(120, 40)
15	markBenchmarkFrame(&frame)
16	r := New(Capabilities{})
17	damage := []Damage{FullRedraw()}
18	b.ReportAllocs()
19	var outBytes int64
20	for b.Loop() {
21		r.Reset()
22		out, err := r.Draw(frame, damage)
23		if err != nil {
24			b.Fatal(err)
25		}
26		if len(out) == 0 {
27			b.Fatal("expected renderer output")
28		}
29		outBytes += int64(len(out))
30	}
31	b.ReportMetric(float64(outBytes)/float64(b.N), "outbytes/op")
32}
33
34func BenchmarkRendererFragmentedDamage(b *testing.B) {
35	const (
36		width  = 120
37		height = 40
38	)
39
40	baseline := NewFrame(width, height)
41	markBenchmarkFrame(&baseline)
42	frame := NewFrame(width, height)
43	markBenchmarkFrame(&frame)
44
45	// Create 256 overlapping or vertically adjacent text rectangles in reverse
46	// row/column order. Canonical damage planning must sort and merge these into
47	// stable per-row spans before emission.
48	damage := make([]Damage, 0, 256)
49	for row := 15; row >= 0; row-- {
50		for col := 15; col >= 0; col-- {
51			x, y := col*7, row*2
52			damage = append(damage, Damage{Kind: DamageText, X: x, Y: y, Width: 8, Height: 2})
53			for dy := range 2 {
54				for dx := range 8 {
55					frame.Set(x+dx, y+dy, Cell{Rune: 'z', Style: DefaultStyle()})
56				}
57			}
58		}
59	}
60
61	r := New(Capabilities{})
62	b.ReportAllocs()
63	var outBytes int64
64	for b.Loop() {
65		// Each iteration starts with the identical pre-update terminal shadow.
66		r.replaceShadow(baseline)
67		out, err := r.Draw(frame, damage)
68		if err != nil {
69			b.Fatal(err)
70		}
71		if len(out) == 0 {
72			b.Fatal("expected renderer output")
73		}
74		outBytes += int64(len(out))
75	}
76	b.ReportMetric(float64(outBytes)/float64(b.N), "outbytes/op")
77}
78
79func BenchmarkRendererScrollFastPath(b *testing.B) {
80	frame := NewFrame(120, 40)
81	markBenchmarkFrame(&frame)
82	r := New(Capabilities{})
83	if _, err := r.Draw(frame, []Damage{FullRedraw()}); err != nil {
84		b.Fatal(err)
85	}
86
87	scrolled := NewFrame(120, 40)
88	copy(scrolled.Cells[0:39*120], frame.Cells[120:40*120])
89	for i := 39 * 120; i < 40*120; i++ {
90		scrolled.Cells[i] = BlankCell()
91	}
92	for x, r := range []rune("new output line") {
93		scrolled.Set(x, 39, Cell{Rune: r, Style: DefaultStyle()})
94	}
95	damage := []Damage{
96		{Kind: DamageScrollUp, X: 0, Y: 0, Width: 120, Height: 40, Count: 1},
97		{Kind: DamageText, X: 0, Y: 39, Width: 120, Height: 1, Count: 1},
98	}
99
100	b.ReportAllocs()
101	var outBytes int64
102	for b.Loop() {
103		r.replaceShadow(frame)
104		out, err := r.Draw(scrolled, damage)
105		if err != nil {
106			b.Fatal(err)
107		}
108		if len(out) == 0 {
109			b.Fatal("expected renderer output")
110		}
111		outBytes += int64(len(out))
112	}
113	b.ReportMetric(float64(outBytes)/float64(b.N), "outbytes/op")
114}

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 12

Tags 11

↑↓ moveenter openesc close