java-topology/defects/rclone-0001/test/test_graceful_shutdown_set.go

99 lines
2.5 KiB
Go

package main
import (
"fmt"
"math/rand"
"slices"
"time"
)
// Simulates the bisync modifyListing graceful shutdown rollback logic.
// BEFORE: slices.Contains(toKeep, f) inside loop over combinedList = O(C*K)
// AFTER: map[string]struct{} lookup = O(C)
func generateFileNames(n int) []string {
names := make([]string, n)
for i := range n {
names[i] = fmt.Sprintf("path/to/file_%06d.dat", i)
}
return names
}
// BEFORE: linear search with slices.Contains
func rollbackBefore(combinedList, toKeep []string) []string {
var toRollback []string
for _, f := range combinedList {
if !slices.Contains(toKeep, f) {
toRollback = append(toRollback, f)
}
}
return toRollback
}
// AFTER: hash set lookup
func rollbackAfter(combinedList, toKeep []string) []string {
toKeepSet := make(map[string]struct{}, len(toKeep))
for _, k := range toKeep {
toKeepSet[k] = struct{}{}
}
var toRollback []string
for _, f := range combinedList {
if _, ok := toKeepSet[f]; !ok {
toRollback = append(toRollback, f)
}
}
return toRollback
}
func main() {
rand.Seed(42)
for _, N := range []int{100, 500, 2000, 10000} {
allFiles := generateFileNames(N)
// 30% kept, 70% to rollback
keepCount := N * 3 / 10
perm := rand.Perm(N)
toKeep := make([]string, keepCount)
for i := range keepCount {
toKeep[i] = allFiles[perm[i]]
}
// combinedList = 4x file lists (simulating oldSrc + oldDst + srcList + dstList)
combinedList := make([]string, 0, N*4)
for range 4 {
combinedList = append(combinedList, allFiles...)
}
// Correctness: both must produce same rollback set
resultBefore := rollbackBefore(combinedList, toKeep)
resultAfter := rollbackAfter(combinedList, toKeep)
if len(resultBefore) != len(resultAfter) {
fmt.Printf("FAIL N=%d: length mismatch %d vs %d\n", N, len(resultBefore), len(resultAfter))
return
}
for i := range resultBefore {
if resultBefore[i] != resultAfter[i] {
fmt.Printf("FAIL N=%d: mismatch at index %d\n", N, i)
return
}
}
// Benchmark BEFORE
start := time.Now()
iters := 5
for range iters {
rollbackBefore(combinedList, toKeep)
}
dBefore := time.Since(start)
// Benchmark AFTER
start = time.Now()
for range iters {
rollbackAfter(combinedList, toKeep)
}
dAfter := time.Since(start)
ratio := float64(dBefore) / float64(dAfter)
fmt.Printf("PASS N=%d (combined=%d, keep=%d): before=%v after=%v ratio=%.1fx\n",
N, len(combinedList), keepCount, dBefore/time.Duration(iters), dAfter/time.Duration(iters), ratio)
}
}