Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Contributions and communications are expected to occur through:

- [GitHub Issues](https://github.com/entireio/cli/issues) - Bug reports and feature requests
- [GitHub Discussions](https://github.com/entireio/cli/discussions) - Questions and general conversation
- [Discord](https://discord.gg/4WXDu2Ph) - Real-time chat and support
- [Discord](https://discord.gg/jZJs3Tue4S) - Real-time chat and support

Please represent the project and community respectfully in all public and private interactions.

Expand Down Expand Up @@ -329,7 +329,7 @@ Join the Entire community:
- **Discord** - [Join our server][discord] for discussions and support
- **GitHub Discussions** - [Join the conversation][discussions]

[discord]: https://discord.gg/4WXDu2Ph
[discord]: https://discord.gg/jZJs3Tue4S
[discussions]: https://github.com/entireio/cli/discussions

---
Expand Down
85 changes: 85 additions & 0 deletions cmd/entire/cli/bench_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package cli

import (
"io"
"testing"

"github.com/entireio/cli/cmd/entire/cli/benchutil"
"github.com/entireio/cli/cmd/entire/cli/paths"
"github.com/entireio/cli/cmd/entire/cli/session"
)

/* To use the interactive flame graph, run:

mise exec -- go tool pprof -http=:8089 /tmp/status_cpu.prof &>/dev/null & echo "pprof server started on http://localhost:8089"

and then go to http://localhost:8089/ui/flamegraph

*/

// BenchmarkStatusCommand benchmarks the `entire status` command end-to-end.
// This is the top-level entry point for understanding status command latency.
//
// Key I/O operations measured:
// - git rev-parse --show-toplevel (RepoRoot, cached after first call)
// - git rev-parse --git-common-dir (NewStateStore, per invocation)
// - git rev-parse --abbrev-ref HEAD (resolveWorktreeBranch, per unique worktree)
// - os.ReadFile for settings.json, each session state file
// - JSON unmarshaling for settings and each session state
//
// The primary scaling dimension is active session count.
func BenchmarkStatusCommand(b *testing.B) {
b.Run("Short/NoSessions", benchStatus(0, false, true))
b.Run("Short/1Session", benchStatus(1, false, true))
b.Run("Short/5Sessions", benchStatus(5, false, true))
b.Run("Short/10Sessions", benchStatus(10, false, true))
b.Run("Short/20Sessions", benchStatus(20, false, true))
b.Run("Detailed/NoSessions", benchStatus(0, true, true))
b.Run("Detailed/5Sessions", benchStatus(5, true, true))
}

// BenchmarkStatusCommand_NoCache simulates the old behavior where getGitCommonDir
// is uncached — every invocation spawns an extra git subprocess.
func BenchmarkStatusCommand_NoCache(b *testing.B) {
b.Run("Short/NoSessions", benchStatus(0, false, false))
b.Run("Short/1Session", benchStatus(1, false, false))
b.Run("Short/5Sessions", benchStatus(5, false, false))
b.Run("Short/10Sessions", benchStatus(10, false, false))
b.Run("Short/20Sessions", benchStatus(20, false, false))
b.Run("Detailed/NoSessions", benchStatus(0, true, false))
b.Run("Detailed/5Sessions", benchStatus(5, true, false))
}

// benchStatus returns a benchmark function for the `entire status` command.
// When useGitCommonDirCache is false, it clears the git common dir cache each
// iteration to simulate the old uncached behavior.
func benchStatus(sessionCount int, detailed, useGitCommonDirCache bool) func(*testing.B) {
return func(b *testing.B) {
repo := benchutil.NewBenchRepo(b, benchutil.RepoOpts{})

// Create active session state files in .git/entire-sessions/
for range sessionCount {
repo.CreateSessionState(b, benchutil.SessionOpts{})
}

// runStatus uses paths.RepoRoot() which requires cwd to be in the repo.
b.Chdir(repo.Dir)
paths.ClearRepoRootCache()
session.ClearGitCommonDirCache()

b.ResetTimer()
for range b.N {
// Always clear RepoRoot to simulate a fresh CLI invocation.
paths.ClearRepoRootCache()

if !useGitCommonDirCache {
// Simulate old behavior: no git common dir cache.
session.ClearGitCommonDirCache()
}

if err := runStatus(io.Discard, detailed); err != nil {
b.Fatalf("runStatus: %v", err)
}
}
}
}
Loading