main f2d166b

benchmark_test.go RawHistoryFolder

1package hints
2
3import (
4	"context"
5	"image"
6	"image/draw"
7	"image/png"
8	"os"
9	"os/exec"
10	"path/filepath"
11	"strconv"
12	"testing"
13	"time"
14)
15
16// TestFrameBenchmark logs counts and timings, never filenames or OCR text.
17func TestFrameBenchmark(t *testing.T) {
18	dir := os.Getenv("NEFERWL_HINT_BENCH_DIR")
19	if dir == "" {
20		t.Skip("set NEFERWL_HINT_BENCH_DIR to a local PNG directory")
21	}
22	if _, err := exec.LookPath("tesseract"); err != nil {
23		t.Skip("tesseract not on PATH")
24	}
25	files, err := filepath.Glob(filepath.Join(dir, "*.png"))
26	if err != nil || len(files) == 0 {
27		t.Fatal("no PNG frames")
28	}
29	// Settings under test: NEFERWL_HINT_BENCH_WORKERS=<n>, NEFERWL_HINT_BENCH_PNG=speed|none.
30	if v, _ := strconv.Atoi(os.Getenv("NEFERWL_HINT_BENCH_WORKERS")); v > 0 {
31		ocrWorkers = v
32	}
33	if os.Getenv("NEFERWL_HINT_BENCH_PGM") == "0" {
34		rawPGM = false
35	}
36	if os.Getenv("NEFERWL_HINT_BENCH_PNG") == "none" {
37		pngLevel = png.NoCompression
38	}
39	for i, file := range files {
40		f, err := os.Open(file)
41		if err != nil {
42			t.Fatal("open frame failed")
43		}
44		src, err := png.Decode(f)
45		_ = f.Close()
46		if err != nil {
47			t.Fatal("decode frame failed")
48		}
49		img := image.NewRGBA(image.Rect(0, 0, src.Bounds().Dx(), src.Bounds().Dy()))
50		draw.Draw(img, img.Bounds(), src, src.Bounds().Min, draw.Src)
51		start := time.Now()
52		words, bands, err := readWords(context.Background(), toGray(img))
53		if err != nil {
54			t.Fatal("recognition failed")
55		}
56		t.Logf("frame=%d px=%d ocr_ms=%.1f words=%d links=%d bands=%d", i, img.Bounds().Dx()*img.Bounds().Dy(), ms(time.Since(start)), len(words), len(textLinks(words, 1)), bands)
57		if os.Getenv("NEFERWL_HINT_BENCH_STRIPS") == "" {
58			continue
59		}
60		// Experimental strips use known OCR word regions, not pixel targets.
61		// This is an oracle comparison, not a production optimization.
62		lines := make([]image.Rectangle, 0, len(words))
63		for _, word := range words {
64			lines = append(lines, word.Rect)
65		}
66		for _, normalized := range []bool{false, true} {
67			begin := time.Now()
68			compact, _, err := readStrips(context.Background(), img, lines, 8, normalized)
69			if err != nil {
70				t.Fatal("strip recognition failed")
71			}
72			t.Logf("frame=%d strips normalized=%t ocr_ms=%.1f words=%d links=%d", i, normalized, ms(time.Since(begin)), len(compact), len(textLinks(compact, 1)))
73		}
74	}
75}
76
77func toGray(img *image.RGBA) *image.Gray {
78	g := image.NewGray(img.Bounds())
79	draw.Draw(g, g.Bounds(), img, img.Bounds().Min, draw.Src)
80	return g
81}

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 26

Tags 10

↑↓ moveenter openesc close