|
| 1 | +package cli |
| 2 | + |
| 3 | +import ( |
| 4 | + "io" |
| 5 | + "testing" |
| 6 | + |
| 7 | + "github.com/entireio/cli/cmd/entire/cli/benchutil" |
| 8 | + "github.com/entireio/cli/cmd/entire/cli/paths" |
| 9 | +) |
| 10 | + |
| 11 | +// BenchmarkStatusCommand benchmarks the `entire status` command end-to-end. |
| 12 | +// This is the top-level entry point for understanding status command latency. |
| 13 | +// |
| 14 | +// Key I/O operations measured: |
| 15 | +// - git rev-parse --show-toplevel (RepoRoot, cached after first call) |
| 16 | +// - git rev-parse --git-common-dir (NewStateStore, per invocation) |
| 17 | +// - git rev-parse --abbrev-ref HEAD (resolveWorktreeBranch, per unique worktree) |
| 18 | +// - os.ReadFile for settings.json, each session state file |
| 19 | +// - JSON unmarshaling for settings and each session state |
| 20 | +// |
| 21 | +// The primary scaling dimension is active session count. |
| 22 | +func BenchmarkStatusCommand(b *testing.B) { |
| 23 | + b.Run("Short/NoSessions", benchStatus(0, false)) |
| 24 | + b.Run("Short/1Session", benchStatus(1, false)) |
| 25 | + b.Run("Short/5Sessions", benchStatus(5, false)) |
| 26 | + b.Run("Short/10Sessions", benchStatus(10, false)) |
| 27 | + b.Run("Short/20Sessions", benchStatus(20, false)) |
| 28 | + b.Run("Detailed/NoSessions", benchStatus(0, true)) |
| 29 | + b.Run("Detailed/5Sessions", benchStatus(5, true)) |
| 30 | +} |
| 31 | + |
| 32 | +func benchStatus(sessionCount int, detailed bool) func(*testing.B) { |
| 33 | + return func(b *testing.B) { |
| 34 | + repo := benchutil.NewBenchRepo(b, benchutil.RepoOpts{}) |
| 35 | + |
| 36 | + // Create active session state files in .git/entire-sessions/ |
| 37 | + for range sessionCount { |
| 38 | + repo.CreateSessionState(b, benchutil.SessionOpts{}) |
| 39 | + } |
| 40 | + |
| 41 | + // runStatus uses paths.RepoRoot() which requires cwd to be in the repo. |
| 42 | + b.Chdir(repo.Dir) |
| 43 | + paths.ClearRepoRootCache() |
| 44 | + |
| 45 | + b.ResetTimer() |
| 46 | + for range b.N { |
| 47 | + // Clear cache each iteration to simulate a fresh CLI invocation. |
| 48 | + // In real usage, each `entire status` call starts cold. |
| 49 | + paths.ClearRepoRootCache() |
| 50 | + |
| 51 | + if err := runStatus(io.Discard, detailed); err != nil { |
| 52 | + b.Fatalf("runStatus: %v", err) |
| 53 | + } |
| 54 | + } |
| 55 | + } |
| 56 | +} |
0 commit comments