diff options
author | Daniel Milde <daniel@milde.cz> | 2024-04-20 01:28:10 +0200 |
---|---|---|
committer | Daniel Milde <daniel@milde.cz> | 2024-04-20 01:30:14 +0200 |
commit | 32e516a464a391d3ea51313327b6cf11a94b89dc (patch) | |
tree | 92ff84cbb17139b651493bc5e5cfcdc0be621891 | |
parent | b8836d336b371e00c44ed61bec34fb3914abc709 (diff) |
chore: benchmark for parallel deletiondundee/feat/bench-deletion
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | bench-delete.md | 4 | ||||
-rw-r--r-- | cmd/deleter/main.go | 109 | ||||
-rw-r--r-- | trace-parallel.out | bin | 0 -> 7566 bytes | |||
-rw-r--r-- | trace-single.out | bin | 0 -> 6708 bytes |
5 files changed, 120 insertions, 0 deletions
@@ -130,6 +130,13 @@ benchmark: 'gdu -npc ~' 'gdu -gnpc ~' 'gdu -npc --use-storage ~' sudo cpupower frequency-set -g schedutil +benchmark-deletion: + hyperfine \ + --export-markdown=bench-delete.md \ + --prepare 'cd test; git init . ; fallocate -l 1G .git/info/file ; dd if=/dev/urandom of=.git/refs/file bs=64M count=8 iflag=fullblock ; dd if=/dev/urandom of=.git/objects/file bs=64M count=8 iflag=fullblock ; cd ..' \ + 'go run ./cmd/deleter/main.go ./test/.git' \ + 'go run ./cmd/deleter/main.go --parallel ./test/.git' + clean: go mod tidy -rm coverage.txt diff --git a/bench-delete.md b/bench-delete.md new file mode 100644 index 0000000..584041c --- /dev/null +++ b/bench-delete.md @@ -0,0 +1,4 @@ +| Command | Mean [ms] | Min [ms] | Max [ms] | Relative | +|:---|---:|---:|---:|---:| +| `go run ./cmd/deleter/main.go ./test/.git` | 840.3 ± 648.5 | 504.2 | 2137.6 | 1.00 | +| `go run ./cmd/deleter/main.go --parallel ./test/.git` | 902.1 ± 885.1 | 476.1 | 3168.0 | 1.07 ± 1.34 | diff --git a/cmd/deleter/main.go b/cmd/deleter/main.go new file mode 100644 index 0000000..a9b36ad --- /dev/null +++ b/cmd/deleter/main.go @@ -0,0 +1,109 @@ +package main + +import ( + "flag" + "fmt" + "io" + "os" + "path/filepath" + "runtime/trace" + "time" + + "github.com/dundee/gdu/v5/pkg/fs" + "github.com/dundee/gdu/v5/pkg/remove" +) + +func main() { + inParallel := flag.Bool("parallel", false, "Delete in parallel") + tracing := flag.Bool("trace", false, "Collect CPU trace") + flag.Parse() + args := flag.Args() + + if len(args) < 1 { + fmt.Println("Usage: [--parallel] directory_to_delete") + return + } + + if info, err := os.Stat(args[0]); os.IsNotExist(err) { + fmt.Println("Path does not exist") + return + } else if !info.IsDir() { + fmt.Println("Path is not directory") + return + } + path, err := filepath.Abs(args[0]) + if err != nil { + fmt.Println("Cannot convert to absolute: ", err.Error()) + } + + deleter := remove.RemoveItemFromDir + if *inParallel { + deleter = remove.RemoveItemFromDirParallel + } + + if *tracing { + f, err := os.Create("trace.out") + if err != nil { + fmt.Println("Trace file cannot be created: ", err.Error()) + return + } + trace.Start(f) + } + + err = deleter(NewDeletedItem(""), NewDeletedItem(path)) + if err != nil { + fmt.Println("Failed with: ", err.Error()) + } + trace.Stop() +} + +func NewDeletedItem(path string) fs.Item { + return &DeletedItem{ + Path: path, + } +} + +type DeletedItem struct { + Path string +} + +func (p *DeletedItem) GetPath() string { + return p.Path +} +func (p *DeletedItem) GetFilesLocked() fs.Files { + var items []fs.Item + entries, err := os.ReadDir(p.Path) + if err != nil { + panic(err) + } + + for _, entry := range entries { + path := filepath.Join(p.Path, entry.Name()) + items = append(items, NewDeletedItem(path)) + } + return items +} +func (p *DeletedItem) IsDir() bool { return true } +func (f *DeletedItem) RemoveFile(item fs.Item) {} + +func (p *DeletedItem) GetName() string { panic("must not be called") } +func (p *DeletedItem) GetFlag() rune { panic("must not be called") } +func (p *DeletedItem) GetSize() int64 { panic("must not be called") } +func (p *DeletedItem) GetType() string { panic("must not be called") } +func (p *DeletedItem) GetUsage() int64 { panic("must not be called") } +func (p *DeletedItem) GetMtime() time.Time { panic("must not be called") } +func (p *DeletedItem) GetItemCount() int { panic("must not be called") } +func (p *DeletedItem) GetParent() fs.Item { panic("must not be called") } +func (p *DeletedItem) SetParent(fs.Item) { panic("must not be called") } +func (p *DeletedItem) GetMultiLinkedInode() uint64 { panic("must not be called") } +func (p *DeletedItem) EncodeJSON(writer io.Writer, topLevel bool) error { panic("must not be called") } +func (p *DeletedItem) UpdateStats(linkedItems fs.HardLinkedItems) { panic("must not be called") } +func (p *DeletedItem) AddFile(fs.Item) { panic("must not be called") } +func (p *DeletedItem) GetFiles() fs.Files { panic("must not be called") } +func (p *DeletedItem) RLock() func() { panic("must not be called") } +func (p *DeletedItem) SetFiles(fs.Files) { panic("must not be called") } +func (p *DeletedItem) GetItemStats( + linkedItems fs.HardLinkedItems, +) (int, int64, int64) { + panic("must not be called") +} diff --git a/trace-parallel.out b/trace-parallel.out Binary files differnew file mode 100644 index 0000000..132fe09 --- /dev/null +++ b/trace-parallel.out diff --git a/trace-single.out b/trace-single.out Binary files differnew file mode 100644 index 0000000..ed01939 --- /dev/null +++ b/trace-single.out |