github.com/charlievieth/fastwalk@v1.0.3/entry_filter_unix_test.go (about)

     1  //go:build (linux || darwin || freebsd || openbsd || netbsd || !windows) && !appengine
     2  // +build linux darwin freebsd openbsd netbsd !windows
     3  // +build !appengine
     4  
     5  package fastwalk
     6  
     7  import (
     8  	"math/rand"
     9  	"runtime"
    10  	"sync"
    11  	"testing"
    12  	"time"
    13  )
    14  
    15  type devIno struct {
    16  	Dev, Ino uint64
    17  }
    18  
    19  func generateDevIno(rr *rand.Rand, ndev, size int) []devIno {
    20  	devs := make([]uint64, ndev)
    21  	for i := range devs {
    22  		devs[i] = rr.Uint64()
    23  	}
    24  	pairs := make([]devIno, size)
    25  	seen := make(map[devIno]struct{}, len(pairs))
    26  	for i := range pairs {
    27  		for {
    28  			di := devIno{
    29  				Dev: devs[rr.Intn(len(devs))],
    30  				Ino: rr.Uint64(),
    31  			}
    32  			if _, ok := seen[di]; !ok {
    33  				pairs[i] = di
    34  				seen[di] = struct{}{}
    35  				break
    36  			}
    37  		}
    38  	}
    39  	rr.Shuffle(len(pairs), func(i, j int) {
    40  		pairs[i], pairs[j] = pairs[j], pairs[i]
    41  	})
    42  	return pairs
    43  }
    44  
    45  func TestEntryFilter_Unix(t *testing.T) {
    46  	rr := rand.New(rand.NewSource(1))
    47  	pairs := generateDevIno(rr, 2, 100)
    48  
    49  	x := NewEntryFilter()
    50  	for _, p := range pairs {
    51  		if x.seen(p.Dev, p.Ino) {
    52  			t.Errorf("duplicate: Dev: %d Ino: %d", p.Dev, p.Ino)
    53  		}
    54  	}
    55  	for _, p := range pairs {
    56  		if !x.seen(p.Dev, p.Ino) {
    57  			t.Errorf("wat: Dev: %d Ino: %d", p.Dev, p.Ino)
    58  		}
    59  	}
    60  }
    61  
    62  func TestEntryFilter_Unix_Parallel(t *testing.T) {
    63  	if testing.Short() {
    64  		t.Skip("Short test")
    65  	}
    66  	wg := new(sync.WaitGroup)
    67  	ready := new(sync.WaitGroup)
    68  	start := make(chan struct{})
    69  	x := NewEntryFilter()
    70  
    71  	numWorkers := runtime.NumCPU() * 2
    72  	if numWorkers < 2 {
    73  		numWorkers = 2
    74  	}
    75  	if numWorkers > 8 {
    76  		numWorkers = 8
    77  	}
    78  
    79  	rr := rand.New(rand.NewSource(time.Now().UnixNano()))
    80  	pairs := generateDevIno(rr, 2, numWorkers*8192)
    81  
    82  	for i := 0; i < numWorkers; i++ {
    83  		wg.Add(1)
    84  		ready.Add(1)
    85  		go func(i int, pairs []devIno) {
    86  			defer wg.Done()
    87  			ready.Done()
    88  			<-start
    89  			for _, p := range pairs {
    90  				if x.seen(p.Dev, p.Ino) {
    91  					t.Errorf("%d: unseen dev/ino: Dev: %d Ino: %d", i, p.Dev, p.Ino)
    92  					return
    93  				}
    94  			}
    95  			for _, p := range pairs {
    96  				if !x.seen(p.Dev, p.Ino) {
    97  					t.Errorf("%d: missed seen dev/ino: Dev: %d Ino: %d", i, p.Dev, p.Ino)
    98  					return
    99  				}
   100  			}
   101  		}(i, pairs[i*numWorkers:(i+1)*numWorkers])
   102  	}
   103  
   104  	ready.Wait()
   105  	close(start)
   106  	wg.Wait()
   107  }
   108  
   109  func BenchmarkEntryFilter_Unix(b *testing.B) {
   110  	if testing.Short() {
   111  		b.Skip("Skipping: short test")
   112  	}
   113  	rr := rand.New(rand.NewSource(1))
   114  	pairs := generateDevIno(rr, 2, 8192)
   115  	x := NewEntryFilter()
   116  
   117  	for _, p := range pairs {
   118  		x.seen(p.Dev, p.Ino)
   119  	}
   120  	if len(pairs) != 8192 {
   121  		panic("nope!")
   122  	}
   123  
   124  	b.ResetTimer()
   125  	b.Run("Sequential", func(b *testing.B) {
   126  		for i := 0; i < b.N; i++ {
   127  			p := pairs[i%8192]
   128  			x.seen(p.Dev, p.Ino)
   129  		}
   130  	})
   131  
   132  	b.Run("Parallel", func(b *testing.B) {
   133  		b.RunParallel(func(pb *testing.PB) {
   134  			for i := 0; pb.Next(); i++ {
   135  				p := pairs[i%8192]
   136  				x.seen(p.Dev, p.Ino)
   137  			}
   138  		})
   139  	})
   140  }