cat / 012
clone

a spreadsheet for the terminal: lotus 1-2-3 looks, google sheets keys and formulas, one go binary

Build UI stress shapes lazily and add selection frames

Dami committed c2188bf
Running one sub-benchmark no longer builds every shape. New cases draw
frames over a standing selection of the whole data or sheet, and extend
such a selection, so the status line's statistics are measured.
commit
c2188bfb5c213c27788046568ff5a3e1d2b3a9d0
parent
1ec8e70633160b80dbe5066fc1b8356104fe92f5
author
Dami <dami.etoile@gmail.com>
1 file changed, +28 -10
Minternal/ui/stress_test.go38++++++++++++++++++++++--------
M internal/ui/stress_test.go +28 -10
@@ -15,8 +15,8 @@ import (
1515 "time"1616 1717 tea "charm.land/bubbletea/v2"18- uv "github.com/charmbracelet/ultraviolet"1918 typesafe "github.com/FelineStateMachine/typesafe-go"19+ uv "github.com/charmbracelet/ultraviolet"2020 2121 "012/internal/jev"2222 "012/internal/sheet"
@@ -75,10 +75,10 @@ func sized(s *sheet.Sheet, w, h int) *Model {
7575 // BenchmarkView is View alone: 012's share of a frame.7676 func BenchmarkView(b *testing.B) {7777 for _, sh := range uiShapes() {78- s := sh.build()78+ s := lazy(sh.build)7979 for _, sz := range termSizes {8080 b.Run(fmt.Sprintf("%s/%dx%d", sh.name, sz.w, sz.h), func(b *testing.B) {81- m := sized(s, sz.w, sz.h)81+ m := sized(s(), sz.w, sz.h)8282 for b.Loop() {8383 m.View()8484 }
@@ -90,10 +90,10 @@ func BenchmarkView(b *testing.B) {
9090 // BenchmarkFrame is a whole frame: View, parse and diff.9191 func BenchmarkFrame(b *testing.B) {9292 for _, sh := range uiShapes() {93- s := sh.build()93+ s := lazy(sh.build)9494 for _, sz := range termSizes {9595 b.Run(fmt.Sprintf("%s/%dx%d", sh.name, sz.w, sz.h), func(b *testing.B) {96- m := sized(s, sz.w, sz.h)96+ m := sized(s(), sz.w, sz.h)9797 t := newFakeTerm(sz.w, sz.h)9898 for b.Loop() {9999 t.frame(m)
@@ -133,7 +133,9 @@ func key(k string) tea.KeyPressMsg {
133133 }134134 135135 // BenchmarkKeystroke is a key press through to its frame, alternating136-// keys that undo each other so the state stays put.136+// keys that undo each other so the state stays put. Cases without keys137+// draw frames over a standing selection (whose statistics the status138+// line shows).137139 func BenchmarkKeystroke(b *testing.B) {138140 cases := []struct {139141 name string
@@ -147,24 +149,28 @@ func BenchmarkKeystroke(b *testing.B) {
147149 {"arrow/longtext", uiShapes()[3], nil, []string{"down", "up"}},148150 {"arrow/names-1000", uiShapes()[4], nil, []string{"down", "up"}},149151 {"arrow/charts-20", uiShapes()[5], nil, []string{"down", "up"}},150- {"select-all/dense-8192x256", uiShapes()[2], []string{"ctrl+a", "ctrl+a"}, []string{"shift+down", "shift+up"}},152+ {"select-data/dense-8192x256", uiShapes()[2], []string{"ctrl+a"}, nil},153+ {"select-sheet/dense-8192x256", uiShapes()[2], []string{"ctrl+a", "ctrl+a"}, nil},154+ {"extend-data/dense-8192x256", uiShapes()[2], []string{"ctrl+a"}, []string{"shift+up", "shift+down"}},151155 {"extend/dense-8192x26", uiShapes()[1], []string{"shift+down"}, []string{"shift+down", "shift+up"}},152156 {"type/fanin-1000", uiShape{"fanin", func() *sheet.Sheet { return stress.FanIn(sheet.MaxRows, 1000) }},153157 nil, []string{"7", "enter", "up"}},154158 {"type/dense-8192x26", uiShapes()[1], nil, []string{"7", "enter", "up"}},155159 }156160 for _, c := range cases {157- s := c.shape.build()161+ s := lazy(c.shape.build)158162 for _, sz := range termSizes[:2] {159163 b.Run(fmt.Sprintf("%s/%dx%d", c.name, sz.w, sz.h), func(b *testing.B) {160- m := sized(s, sz.w, sz.h)164+ m := sized(s(), sz.w, sz.h)161165 t := newFakeTerm(sz.w, sz.h)162166 for _, k := range c.setup {163167 m.Update(key(k))164168 }165169 i := 0166170 for b.Loop() {167- m.Update(key(c.keys[i%len(c.keys)]))171+ if len(c.keys) > 0 {172+ m.Update(key(c.keys[i%len(c.keys)]))173+ }168174 t.frame(m)169175 i++170176 }
@@ -210,6 +216,18 @@ func BenchmarkJEV(b *testing.B) {
210216 }211217 }212218 219+// lazy builds a sheet on first use, so running one sub-benchmark doesn't220+// build every shape.221+func lazy(build func() *sheet.Sheet) func() *sheet.Sheet {222+ var s *sheet.Sheet223+ return func() *sheet.Sheet {224+ if s == nil {225+ s = build()226+ }227+ return s228+ }229+}230+213231 // drain runs cmd and every command its messages lead to, breadth first,214232 // like Bubble Tea's event loop with instant commands.215233 func drain(m *Model, cmd tea.Cmd) {