@@ -0,0 +1,227 @@
9+ "github.com/bmatcuk/doublestar/v4"
12+// createTestWorkspace creates a temporary workspace with test files
13+func createTestWorkspace(tb testing.TB) string {
14+ tmpDir, err := os.MkdirTemp("", "watcher_test")
19+ // Create test files for Go project
20+ testFiles := []string{
27+ "internal/config.go",
38+ for _, file := range testFiles {
39+ fullPath := filepath.Join(tmpDir, file)
40+ dir := filepath.Dir(fullPath)
42+ if err := os.MkdirAll(dir, 0755); err != nil {
46+ if err := os.WriteFile(fullPath, []byte("// test content"), 0644); err != nil {
54+// simulateOldApproach simulates the old file opening approach with per-file delays
55+func simulateOldApproach(workspacePath string, serverName string) (int, time.Duration) {
59+ // Define patterns for high-priority files based on server type
60+ var patterns []string
76+ // OLD APPROACH: For each pattern, find and open matching files with per-file delays
77+ for _, pattern := range patterns {
78+ matches, err := doublestar.Glob(os.DirFS(workspacePath), pattern)
83+ for _, match := range matches {
84+ fullPath := filepath.Join(workspacePath, match)
85+ info, err := os.Stat(fullPath)
86+ if err != nil || info.IsDir() {
90+ // Simulate file opening (1ms overhead)
91+ time.Sleep(1 * time.Millisecond)
94+ // OLD: Add delay after each file
95+ time.Sleep(20 * time.Millisecond)
98+ if filesOpened >= 5 {
104+ return filesOpened, time.Since(start)
107+// simulateNewApproach simulates the new batched file opening approach
108+func simulateNewApproach(workspacePath string, serverName string) (int, time.Duration) {
112+ // Define patterns for high-priority files based on server type
113+ var patterns []string
117+ patterns = []string{
123+ patterns = []string{
129+ // NEW APPROACH: Collect all files first
130+ var filesToOpen []string
132+ // For each pattern, find matching files
133+ for _, pattern := range patterns {
134+ matches, err := doublestar.Glob(os.DirFS(workspacePath), pattern)
139+ for _, match := range matches {
140+ fullPath := filepath.Join(workspacePath, match)
141+ info, err := os.Stat(fullPath)
142+ if err != nil || info.IsDir() {
146+ filesToOpen = append(filesToOpen, fullPath)
148+ // Limit the number of files per pattern
149+ if len(filesToOpen) >= 5 {
155+ // Open files in batches to reduce overhead
157+ for i := 0; i < len(filesToOpen); i += batchSize {
158+ end := min(i+batchSize, len(filesToOpen))
160+ // Open batch of files
161+ for j := i; j < end; j++ {
162+ // Simulate file opening (1ms overhead)
163+ time.Sleep(1 * time.Millisecond)
167+ // Only add delay between batches, not individual files
168+ if end < len(filesToOpen) {
169+ time.Sleep(50 * time.Millisecond)
173+ return filesOpened, time.Since(start)
176+func BenchmarkOldApproach(b *testing.B) {
177+ tmpDir := createTestWorkspace(b)
178+ defer os.RemoveAll(tmpDir)
181+ for i := 0; i < b.N; i++ {
182+ simulateOldApproach(tmpDir, "gopls")
186+func BenchmarkNewApproach(b *testing.B) {
187+ tmpDir := createTestWorkspace(b)
188+ defer os.RemoveAll(tmpDir)
191+ for i := 0; i < b.N; i++ {
192+ simulateNewApproach(tmpDir, "gopls")
196+func TestPerformanceComparison(t *testing.T) {
197+ tmpDir := createTestWorkspace(t)
198+ defer os.RemoveAll(tmpDir)
200+ // Test old approach
201+ filesOpenedOld, oldDuration := simulateOldApproach(tmpDir, "gopls")
203+ // Test new approach
204+ filesOpenedNew, newDuration := simulateNewApproach(tmpDir, "gopls")
206+ t.Logf("Old approach: %d files in %v", filesOpenedOld, oldDuration)
207+ t.Logf("New approach: %d files in %v", filesOpenedNew, newDuration)
209+ if newDuration > 0 && oldDuration > 0 {
210+ improvement := float64(oldDuration-newDuration) / float64(oldDuration) * 100
211+ t.Logf("Performance improvement: %.1f%%", improvement)
213+ if improvement <= 0 {
214+ t.Errorf("Expected performance improvement, but new approach was slower")
218+ // Verify same number of files opened
219+ if filesOpenedOld != filesOpenedNew {
220+ t.Errorf("Different number of files opened: old=%d, new=%d", filesOpenedOld, filesOpenedNew)
223+ // Verify new approach is faster
224+ if newDuration >= oldDuration {
225+ t.Errorf("New approach should be faster: old=%v, new=%v", oldDuration, newDuration)